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。(转)

本站公众号
   欢迎关注本站公众号,获取更多信息