每日一个解决问题:事务无法回滚是什么原因?

文章详细介绍了在MySQL中可能导致事务隐式提交的各种情况,包括DDL(如ALTER、CREATE、DROP)操作,DCL(如GRANT、REVOKE)操作,新事务开启,锁定和解锁表,从机操作,以及其他如刷新权限、优化表等操作。作者强调在事务中应避免混合DDL语句,并推荐只使用DML(INSERT/DELETE/UPDATE/SELECT)以防止遇到不可预期的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

今天在码代码时发现事务不回滚了,学过MySQL 事务小伙伴们都懂,通过 begin 开启事务,通过 commit 提交事务或者通过 rollback 回滚事务。

正常来说,当我们开启一个事务之后,需要 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、从机的操作

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

6、其他表操作

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

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

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

7. 最佳实践

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

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

出世&入世

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值