對mysql事務提交 回滾的錯誤理解

2021-09-08 05:04:21 字數 2793 閱讀 5054

一、起因

begin或者start transaction開始乙個事務

rollback事務回滾

commit 事務確認

人們對事務的解釋如下:事務由作為乙個單獨單元的乙個或多個sql語句組成,如果其中乙個語句不能完成,整個單元就會回滾(撤銷),所有影響到的資料將返回到事務開始以前的狀態。因而,只有事務中的所有語句都成功地執行才能說這個事務被成功地執行。

這句話本身沒有什麼問題,問題是我給理解錯了,我測試中問題描述為如下:

mysql事務中有兩條insert語句,其中第二條語句是錯誤的,在執行完事務後,第一條仍然插進去了,**如下。

//建立表:

create table `test_tab` (

`f1` int(11) not null ,

`f2` varchar(11) default null ,

primary key (`f1`)

)engine=innodb

//執行事務:

start transaction;

insert into test_tab values (1, '2');

insert into test_tab values (1, '3');

commit;

(錯誤:這只是我一開始的認為)一開始認為只要把事務寫出來,最後用commit提交一下,資料庫會自動判斷這些語句是否全執行成功,如果成功則把所有的資料插入到資料庫,如果有一條失敗就自動回滾至原始狀態!顯然我認為錯了。

我執行上面的語句後的結果是:

[sql]start transaction;

受影響的行: 0

[sql]

insert into test_tab values (1, '2');

受影響的行: 1

[sql]

insert into test_tab values (1, '3');

[err] 1062 - duplicate entry '1' for key 'primary'

我們看結果可以知道insert into test_tab values (1, '3');這一句因為主鍵衝突執行失敗,從而這一條下面的commit也沒有執行。

需要注意的是:這時已經開啟了乙個事務,並且已經執行了一條正確的插入語句,雖然沒有體現在資料庫中,但如果以後在該連線中又執行了一條commit 或begin或start transaction(新開乙個事務會將該鏈結中的其他未提交的事務提交,相當於commit!)你會發現已經將剛才的insert into test_tab values (1, '2');寫進了資料庫。

所以事務的回滾不是這麼理解的,正確的理解應該是,如果事務中所有sql語句執行正確則需要自己手動提交commit;否則有任何一條執行錯誤,需要自己提交一條rollback,這時會回滾所有操作,而不是commit會給你自動判斷和回滾。

二 解決辦法

c++呼叫方式:(簡單示例)

先定義乙個變數標誌bool m_flag=true;

再執行事務和sql語句如:(execute為自己寫的函式,如下)

execute( m_sqlcon, 「begin」);

execute(m_sqlcon,」insert into test_tab values (1, '2')」);

execute(m_sqlcon,」insert into test_tab values (1, '3')」);

如果執行過程中任意一語句出錯則將該標誌m_flag置為false。

這時不應該去提交commit,而是用乙個函式去判斷標誌是否為false,如果為false說明執行的sql語句中有失敗的,就執行rollback,否則說明全部正確,執行commit。如下面的 commit_transaction()方法。

**大致如下,如使用需要修改!

1 privat void execute(mysql m_sqlcon, string sqlstatement)

2 7 public bool commit_transaction()

8 15 else

16

22 }

23 return true;

24 }

2.利用儲存過程:

1 create procedure pro2()

2 begin

3 declare t_error integer;

4 declare continue handler for sqlexception set t_error = 1;

5 6 start transaction;

7 insert into test_tab values (1, '2');

8 insert into test_tab values (1, '3');

9

10 if t_error = 1 then

11 rollback;

12 else

13 commit;

14 end if;

15 end

然後呼叫 call  pro2()

這個直接可以利用mysql去決定他應該是回滾還是提交。

**:

Fescar RM 全域性事務提交回滾流程

這篇文章的目的主要是講解rm在接收tc的請求後執行全域性分支事務提交 dobranchcommit 和全域性分支事務回滾 dobranchrollback 的流程。全域性的分支事務提交過程和回滾過程也算rm處理流程中核心的一環,了解以後並結合之前講解的本地事務提交流程就能夠較好的理解整個過程了。整體...

Spring手動管理事務提交 回滾

配置好spring事務之後 spring事務配置,可參見其它檔案 我們可以簡單的新增乙個注釋 transactional實現事務,但是如果方法中catch了異常,此異常沒有丟擲,那麼事務將不會生效。可以在catch中加入如下 實現事務回滾功能 transactional rollbackfor ex...

另外乙個實現事務提交 回滾的方法

我們實現乙個資料庫事務,目前常用的,要麼是在儲存過程裡面寫上,要麼就在ado.net層次控制,其實還有一種在asp頁面層次中實現。步驟如下 新增引用system.enterpriseservices.dll using system.enterpriseservices 隨便建立乙個按鈕,在按鈕中進...