乐趣区

关于mysql:咦为什么我的事务回滚不了

MySQL 事务小伙伴们都懂,通过 begin 开启事务,通过 commit 提交事务或者通过 rollback 回滚事务。

在后面的文章中,松哥也和大家聊了一些事物原理以及相干的细节,小伙伴们能够回顾一下:

  • MVCC 水略深,然而弄懂了真的好爽!
  • 一致性视图是啥时候建设的?
  • 四个案例看懂 MySQL 事务隔离级别

失常来说,当咱们开启一个事务之后,须要 commit 或者 rollback 来完结一个事务的,然而有时候,一些操作会主动帮咱们提交事务,如果大家不理解隐式事务的话,那么在具体应用事务的事务可能就会遭逢一些莫名其妙的问题。

1. DDL 操作

首先一点就是 DDL 操作会隐式提交事务,这个松哥在之前的文章中其实有说过,咱们再来一起回顾下:

所有的 DDL 语句都会导致事务隐式提交,换句话说,当你在执行 DDL 语句前,事务就曾经提交了。这就意味着带有 DDL 语句的事务未来没有方法 rollback。

我举一个简略的例子,大家一起来看下:

咱们来一起看下我这里的测试逻辑:

  1. 首先查问总记录数有四条。
  2. 开启一个事务。
  3. 执行一条删除语句。
  4. alter 表,新增一个字段。
  5. 回滚。
  6. 再次查问数据。

到第六步的时候,咱们发现查问到的数据只剩三条了,阐明第五步的回滚并没有失效。起因就在于执行 alter 之前,事务曾经被隐式提交了。

所以小伙伴们在日常开发中,最好不要在事务中混有 DDL 语句,DDL 语句和 DML 语句离开写。

对于下面的案例,如果大家去掉第四步的 alter,那么回滚是能够回滚胜利的,这个小伙伴们本人来测试,我就不演示了。

当然 DDL 操作可不仅仅是 alter,其余的 如 CREATE、DROP 等操作也会导致事务隐式提交,这里松哥就不一一举例了,小伙伴们能够自行尝试。

2. DCL 操作

DDL 和 DML 大家应该常常接触到,然而 DCL 可能有小伙伴不分明,DCL 其实就是 Data Control Language,中文译作数据管制语言,咱们日常受权或者回收数据库上的权限所应用的 GRANT、REVOKE 等,就算是 DCL 操作。

我举个简略例子:

能够看到,跟第一大节的测试步骤一样,只不过第四步换成一个 GRANT 语句,那么最终的事务回滚也会生效,起因就在于事务曾经提交了。

当然,除了 GRANT 和 REVOKE 之外,其余的创立、更新或者删除用户的操作也会导致事务隐式提交。次要有:

  • CREATE USER…
  • DROP USER…
  • ALTER USER…
  • SET PASSWORD…

3. 新事务开启

一个事务还没提交,后果你又开启了一个新的事务,那么此时前一个事务也会隐式提交。看个例子:

这个好了解,不多说。

4. 各种锁操作

给表上锁、解锁也会导致事务隐式提交。如下:

上锁的 SQL 如 lock tables table_name read|write,会导致事务隐式提交,解锁的 SQL 如 unlock tables 也会导致事务被隐式提交。

除了表锁,一些全局锁如 FTWRL 也会导致事务的隐式提交,如下:

5. 从机的操作

之前松哥有教大家如何大家 MySQL 主从:

  • MySQL8 主从复制踩坑指南

咱们在从机上执行的一些操作如 start slavestop slavereset slave 以及 change master to 等语句也会隐式提交事务。

6. 其余表操作

其余的一下操作如刷新权限(flush privileges)、优化表(optimize table)、修复表(repair table)等操作,也会导致事务的隐式提交。

我在网上看有人说 LOAD DATA 会隐式提交事务,松哥亲测貌似并不会,如下图:

LOAD DATA 仿佛并没有导致事务隐式提交,欢送大家提出不同见解一起探讨。

7. 最佳实际

那么多隐式提交,我怎么记得住呀?其实不必背,你只有记着 事务里只写增删改查(INSERT/DELETE/UPDATE/SELECT),就不会错啦!

退出移动版