數據庫的隱式提交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。(轉)