MySQL事务-验证DDL语句的隐式提交

2018-06-17  本文已影响147人  basetree

情景:将一组数据写入数据库的四张表a,b,c,d(期间会进行建表操作)中,要求这一操作具有原子性。

代码逻辑:
(1) 开启事务。
(2) 对数据库进行读写或改变数据对象行为(执行DDL或者DML)。
(3) 异常处理,如果捕获到异常,则对事务进行回滚,如果没有异常,则进行提交。

测试,出现了两种情况:
(1) 捕获到异常后回滚成功。(达到目的)
(2) 捕获到异常后回滚失败。(失败状态)

分析:代码逻辑没有多大问题,经过查阅资料,原来是DDL的隐式提交造成的。DML一旦出现异常,是可以进行正常的回滚的,但是只要一执行到DDL,不管这句DDL有没有报异常,都会进行一次commit,这就造成了这样的情形,成功表现为该操作具有原子性,但是一旦DDL出现异常,会把前面所执行的DML全部提交,所以,就使得捕获到异常后回滚失败,导致操作失去原子性。以下对该过程进行验证。

DDL,DML和DCL简介

1. DDL: 数据定义语言,用于定义和管理 SQL 数据库中的所有对象的语言,这种对象包括数据库本身,以及数据库对象,如表、视图等等,DDL对这些对象和属性的管理和定义具体表现在create、drop和alter上。

DDL的主要语句(操作)
(1) create语句:可以创建数据库和数据库的一些对象。
(2) drop语句:可以删除数据表、索引、触发程序、条件约束以及数据表的权限等。
(3) alter语句:修改数据表定义及属性。

2. DML:数据操作语言,SQL中处理数据等操作统称为数据操纵语言,用于操作数据库对象中包含的数据,也就是说操作的单位是记录。

DML的主要语句(操作)
(1) insert语句 :向数据表张插入一条记录。
(2) delete语句:删除数据表中的一条或多条记录,也可以删除数据表中的所有记录,但是,它的操作对象仍是记录。
(3) update语句:用于修改已存在表中的记录的内容。

3. DCL:数据控制语言,用来授予或回收访问数据库的某种特权,并控制数据库操纵事务发生的时间及效果,对数据库实行监视等。

DCL的主要语句(操作)
(1) grant语句:允许对象的创建者给某用户或某组或所有用户(PUBLIC)某些特定的权限。
(2) revoke语句:可以废除某用户或某组或所有用户访问权限

DDL语句的隐式提交

1.首先验证DML语句可以进行正常的事务回滚,这里以表test为实验对象,下面为该表的结构

test表结构

这张表很简单,只有一个id字段。

1. 开启事务。

开启事务

2. 向test表写入1。

3. 回滚事务并并查看test表。

回滚事务

由结果可以看到,test表中的id值为空,这说明事务回滚成功。

删除上面写入的1,接下来为验证DDL的隐式提交。

1. 开启事务。

2. 向test表写入2。

3. 创建数据表test2。(忽略建表的时长...)

创建数据表test2

4.回滚事务并查看test表的数据。

由上面的结果可以知道,id=2在test表中仍然存在,说明回滚失败了。

分析:查看binlog (可以看我的另一篇binlog的学习总结MySQL的binlog日志 - 简书)

binlog日志

执行这两条语句,是最后才rollback的,期间并没有做任何的commit,但是在执行完第一条语句后,从binlog中可以看到,又执行了一次commit,这是为什么呢,原因就是执行了后面的DDL语句,我们向test表写入id=2后又创建了一张test2表,就是这条创建语句,也就是DDL,会先commit一次,然后再执行,最后再commit。所以,就出现了在执行完第一条语句后commit了一次。也就是说,后面的rollback针对的是一个空事务,因此看到的就是回滚事务失败,其实并不是回滚失败,而是DDL不管成功与否,它都会先commit一次,只不过在出现异常时就会导致该操作的非原子性。

结论:DDL操作是隐性提交的!不能rollback,当执行到DDL语句时,会隐式的将当前会话的事务进行一次“commit”操作!

补充:为什么要在DDL上进行自动commit?TOM在asktom上给出了如下回答

Tom说:

a user that gets blocked on the "do the ddl" inside the savepoint is blocked on the transaction -- not the "subtransaction".  Hence it would block people on the data dictionary -- a place we cannotafford to get jammed up.The data dictionary is "special" -- it drives the rest of the system.  If portions of it get lockedup for extended periods of time -- it could be deadly.

DDL操作也就是数据定义语言,对表的结构进行修改,这个修改其实就是对数据字典中表的定义进行了修改。DDL操作发生了阻塞,那么”阻塞“这个动作其实是发生在了数据字典表上,在数据字典上发生严重的阻塞可不是一个小问题,数据字典和整个数据库相关连着,在数据字典上的长期阻塞可能会造成严重的问题。因此,在每个DDL执行后自动commit,提高数据库的整天性能。



上一篇 下一篇

猜你喜欢

热点阅读