You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MySQL中UPDATE自增语句在RR隔离级下的异常行为问询

MySQL RR隔离级下UPDATE语句的行为解析

问题场景

初始user表中id=8的fans值为0,使用MySQL 8.0.41(InnoDB引擎,REPEATABLE-READ隔离级),操作步骤如下:

  • 开启事务A,执行SELECT * from user WHERE id = 8;,查询结果fans=0,保持事务未提交;
  • 开启事务B,执行UPDATE user SET fans = fans +1 where id = 8;并提交,此时表中该记录fans=1;
  • 事务A中再次执行SELECT * from user WHERE id = 8;,结果仍为fans=0,符合RR隔离级预期;
  • 事务A中执行UPDATE user SET fans = fans +1 where id = 8;后,再次查询发现fans=2,提交事务A后最终值为2。

疑问:这是自增语句的特殊设计,还是异常?

技术解析

这不是异常,是InnoDB在REPEATABLE-READ(RR)隔离级下的正常行为,核心原因是快照读与当前读的区别,以及UPDATE语句的执行逻辑:

1. 快照读与当前读的差异

  • 普通SELECT语句在RR隔离级下是快照读:基于事务启动时的一致性快照返回数据,所以事务A两次普通查询都能看到初始的fans=0,符合RR的可重复读特性。
  • UPDATE语句属于当前读:执行时会直接读取最新的提交版本数据,并且会对目标记录加排他锁。

2. UPDATE语句的执行逻辑

事务A执行UPDATE user SET fans = fans +1 where id = 8;时,流程是:

  1. 以当前读的方式获取该记录的最新提交版本(即事务B提交后的fans=1);
  2. 基于这个最新值计算fans+1,得到2;
  3. 将计算后的值写入事务A的本地快照中;
  4. 此时事务A内再执行普通SELECT,会读取自己事务内已修改的快照数据,所以看到的是fans=2。

3. 与RC隔离级的本质区别

RC隔离级下普通查询会直接读取最新提交版本,但这里事务A的普通查询仍然是快照读——只是UPDATE操作触发了当前读并修改了自身快照,后续查询看到的是自己修改后的数据,而非其他事务的提交数据。如果事务A在UPDATE后,其他事务再修改该记录,事务A的普通查询还是看不到外部的修改,这和RC的行为有本质区别。

4. 与自增语句无关

这种行为和fans = fans +1的自增语法没有关系,任何基于当前记录值修改的UPDATE语句(比如fans = fans -1、score = score * 2)都会触发相同逻辑,核心是UPDATE的当前读特性。

内容的提问来源于stack exchange,提问作者Billy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 20:45:01