目录
0.从修改表结构语句开始
1.DDL(Data Definition Language) 数据定义语言
2.DCL(Data Control Language) 数据控制语言
3.在该事务还没提交时开启新事务
4.锁操作
5.行政声明语句
6.主从复制的从机操作
7.如何避免出现隐式提交导致的错误
0.从修改表结构语句开始
试想在这个场景,客户A开启一个事务,修改表1第一个字段的值,而之后客户B此时在删除表1结构的第一个字段,那这时候就会出问题了。
元数据锁(MDL)可以解决这个问题。该锁是系统自动控制的,无需显示使用的,在访问一张表的时候会自动加上的。这个特性是在MySQL5.5中引入的。
- 当对一张表进行增删改查的时候,加MDL读锁(共享锁)
- 当对表结构进行变更操作的时候,加MDL写锁(排他)
MDL锁主要作用是维护表元数据的数据一致性,是为了避免DML语句和DDL冲突,保证读写的正确性。
即是上面所说的场景,客户B在修改表1结构时候就会被阻塞,直到客户A提交了事务才删除成功。
那反过来想一种场景:客户B先开启事务,删除表1结构的一个字段,没有提交;之后客户A查看表1数据。
那按照之前的分析,客户A的查看应该是会被阻塞的,可事实是没有被阻塞。左边的事务还没提交,右边的会话就可以看到左边事务的结果了。
所以可以想到该修改表结构语句的事务是默认自动提交的,隐式帮我们提交了事务。
有些语句隐式结束当前会话中任何活动的事务,就好像您在执行该语句之前完成了COMMIT一样,这样使用rollback就无效了。
这里要注意的是:是在执行修改表结构语句之前,就隐式提交了事务,不是执行了修改表结构语句后才提交。
接下来就讲讲有哪些语句不能回滚的。
1.DDL(Data Definition Language) 数据定义语言
前面的修改表结构就是DDL语句。
备注:若不了解DDL,可以查看该文章MySQL的SQL语句
所有的 DDL 语句都会导致事务隐式提交。即是当你在执行 DDL 语句前,事务就已经提交了。这就意味着带有 DDL 语句的事务将来没有办法 rollback。
看例子:
在第5步查看结果的时候,发现表和插入的数据都有了,说明回滚没有生效。原因是在第3步,执行DDL语句之前事务就被隐式提交。
DDL语句会进行隐式提交,是不能rollback的,所以大家在日常开发中一定要注意。
建议:最好不要在事务中混有 DDL 语句,DDL 语句和 DML 语句分开写。
为什么DDL语句会隐式提交?
因为DDL是数据定义语言,在我们的数据库中承担着创建,删除和修改的重要的职责。一旦发生问题,带来的后果很可能是不可估量的。于是在每执行完一次后就进行提交,可以保证流畅性,数据不会发生阻塞,同时也会提高数据库的整体性能。
2.DCL(Data Control Language) 数据控制语言
这个语句主要是管理用户,权限所使用的 GRANT、REVOKE 等。
看例子:
步骤5查看数据,显示数据已被修改,说明回滚无效,即在执行DCL语句前事务已隐式提交了。
除了常见的 GRANT 和 REVOKE 之外,其他的创建、更新或者删除用户、修改密码等的操作也会导致事务隐式提交。主要有:
- CREATE USER…
- DROP USER…
- ALTER USER…
- SET PASSWORD…
3.在该事务还没提交时开启新事务
一个事务还没提交时,跟着你又开启了一个新的事务,那么此时前一个事务也会隐式提交。
看例子:
4.锁操作
给表上锁、解锁会导致事务隐式提交,全局锁也会导致事务隐式提交。
5.行政声明语句
ANALYZE TABLE(分析表),CHECK TABLE(检查表是否有错误),FLUSH PRIVILEGES(刷新权限),OPTIMIZE TABLE,REPAIR TALBE(修复表),RESET(用于重置服务器的某些内部状态)。
上述操作也会导致事务的隐式提交。
6.主从复制的从机操作
在从机上执行的一些操作如 start slave
、stop slave
、reset slave
以及 change master to
等语句也会隐式提交事务。
7.如何避免出现隐式提交导致的错误
在事务过程中,就只对表数据进行增删改查。
需要对表结构操作的就要等退出事务后再操作。
主要参考来源:MySQL 8.0 参考手册