save?commit

數據庫的隱式提交html

先看一段SQL,最後一條SQL的輸出你認爲是什麼?mysql

 
1
2
3
4
5
6
7
SET AUTOCOMMIT = 1;
BEGIN ;
INSERT INTO t1 VALUES (1);
CREATE TABLE t2 (pk int primary key );
INSERT INTO t2 VALUES (2);
ROLLBACK ;
SHOW TABLES;

答案是:t1, t2都存在!sql

 
1
2
3
4
5
6
7
8
mysql> show tables;
+ ----------------+
| Tables_in_test |
+ ----------------+
| t1             |
| t2             |
+ ----------------+
2 rows in set (0.00 sec)


更奇怪的是:t1中的1也插入成功了!數據庫

 
1
2
3
4
5
6
7
mysql> select * from t1;
+ ----+
| pk |
+ ----+
|  1 |
+ ----+
1 row in set (0.00 sec)

爲何ROLLBACK沒有生效呢?答案是:Implict Commit
執行CREATE TABLE語句前,以前的事務被隱式提交。由於AUTOCOMMIT=1,因此提交後也不會自動新建立任何事務,INSERT語句執行後當即提交,ROLLBACK不會做用在任何事務上,因此獲得了咱們最後看到的結果。數據結構

稍微改一下,讓AUTOCOMMIT=0,會怎樣呢?分佈式

 
1
2
3
4
5
6
7
SET AUTOCOMMIT = 0;
BEGIN ;
INSERT INTO t1 VALUES (1);
CREATE TABLE t2 (pk int primary key );
INSERT INTO t2 VALUES (2);
ROLLBACK ;
SHOW TABLES;

答案是:t1, t2都存在!插入到t1中的1被提交(插入成功)但插入到t2中得2被回滾(沒有插入成功)。之因此t1中的1被提交,是由於CREATE TABLE致使ImplictCOMMIT(注意,是COMMIT,不是ROLLBACK哦!),執行INSERT的時候,會自動開啓一個新事務(AUTOCOMMIT=0的語義要求的行爲)。因此t2中的2被ROLLBACK回滾。spa

爲何部分操做會致使Implict Commit?爲何這樣設計?設計

爲了保證直觀上的原子性。假設不作Implict Commit,看看上面的語句會怎樣:用戶的心理預期是回滾t1的INSERT操做,以及t2的CREATE操做,INSERT操做。若是咱們有能力作到這樣,那的確是很完美的。但實際上咱們很難作到,特別是在分佈式系統中更難!由於CREATE TABLE操做背後涉及到了大量的操做,不單單包括對核心表的操做,還包括大量內存數據結構的更新(如Schema),以及存儲系統的變動(如建立相應的數據塊),工程上很難把這些操做作成原子的。code

那麼,應該如何作呢?比較折中的方式就是跟用戶作一個約定:CREATE TABLE操做總默認COMMIT它以前的事務,這就是implict commit。htm

從MySQL文檔看,他們作這一塊的時候遇到了不少問題,至少在這裏踩過兩個坑。而且,隨着版本的進化,他們還不斷的讓更多語句能引起implict commit。(轉)

本站公眾號
   歡迎關注本站公眾號,獲取更多信息