标签:
先看一段SQL,最后一条SQL的输出你认为是什么?
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都存在!
mysql> show tables; +----------------+ | Tables_in_test | +----------------+ | t1 | | t2 | +----------------+ 2 rows in set (0.00 sec)
mysql> select * from t1; +----+ | pk | +----+ | 1 | +----+ 1 row in set (0.00 sec)
稍微改一下,让AUTOCOMMIT=0,会怎样呢?
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回滚。
为什么部分操作会导致Implict Commit?为什么这样设计?
为了保证直观上的原子性。假设不做Implict Commit,看看上面的语句会怎样:用户的心理预期是回滚t1的INSERT操作,以及t2的CREATE操作,INSERT操作。如果我们有能力做到这样,那的确是很完美的。但实际上我们很难做到,特别是在分布式系统中更难!因为CREATE TABLE操作背后涉及到了大量的操作,不仅仅包括对核心表的操作,还包括大量内存数据结构的更新(如Schema),以及存储系统的变更(如创建相应的数据块),工程上很难把这些操作做成原子的。
那么,应该如何做呢?比较折中的方式就是跟用户做一个约定:CREATE TABLE操作总默认COMMIT它之前的事务,这就是implict commit。
从MySQL文档看,他们做这一块的时候遇到了很多问题,至少在这里踩过两个坑。并且,随着版本的进化,他们还不断的让更多语句能引发implict commit。到底哪些语句会引发implict commit,请参考MySQL文档:
http://dev.mysql.com/doc/refman/5.1/en/implicit-commit.html
数据库中为什么需要Implict Commit(隐式提交事务)
标签:
原文地址:http://blog.csdn.net/maray/article/details/46410817