假设数据库隔离级别为 RR,事务 A 先执行普通SELECT * FROM user WHERE id < 5(快照读),此时事务 B 插入 id=3 的行并提交,事务 A 再次执行相同的普通 SELECT,能看到 id=3 的行吗?为什么?
完整解析
结论:事务 A看不到 id=3 的行。
核心原因(结合 RR 级别 ReadView 规则):
- RR 级别 ReadView 的生成规则 :事务 A 第一次执行普通 SELECT(快照读)时,会生成一个固定的 ReadView ,这个 ReadView 包含了 "生成瞬间的活跃事务 ID 列表、min_trx_id、max_trx_id" 等关键信息,且在事务 A 提交前不会更新、不会重建;
- 数据可见性判断 :
- 事务 B 是在事务 A 生成 ReadView 之后开启并提交的,因此事务 B 的事务 ID ≥ ReadView 的
max_trx_id(高水位线); - 根据 ReadView 的可见性规则:数据行的修改事务 ID ≥
max_trx_id时,该数据对当前事务不可见; - 即使事务 B 提交了 id=3 的行,事务 A 的快照读仍会复用最初的 ReadView,因此无法看到这个新插入的行。
- 事务 B 是在事务 A 生成 ReadView 之后开启并提交的,因此事务 B 的事务 ID ≥ ReadView 的

再来分析第二种情况(在第一问的情况下)
若事务 A 后续执行UPDATE user SET name = 'test' WHERE id < 5(当前读),能修改到事务 B 插入的 id=3 的行吗?这个过程中会触发什么锁机制?
1. 为什么能修改到 id=3 的行?(当前读 vs 快照读的本质区别)
- 快照读(普通 SELECT)依赖 ReadView 读取历史版本,而当前读(UPDATE/DELETE/SELECT ... FOR UPDATE)不依赖 ReadView,会直接读取数据的最新版本;
- 事务 B 已经提交了 id=3 的行,该行是数据库中的 "最新数据",因此事务 A 执行 UPDATE(当前读)时,会扫描到这个最新的 id=3 的行,并执行修改操作;
- 这也是 RR 级别下 "极特殊幻读场景" 的体现:快照读看不到,但当前读能修改到,看似 "矛盾",实则是两种读取方式的机制不同。
2. 触发的锁机制(Next-Key Lock):
事务 A 执行UPDATE user SET name = 'test' WHERE id < 5时,InnoDB 会先执行 "当前读扫描",再加锁,过程如下:
- 第一步:扫描最新数据:遍历 id < 5 的所有行(包括事务 B 插入的 id=3 的行);
- 第二步:加记录锁 :给 id=3 的行加记录锁,防止其他事务同时修改 / 删除这行;
- 第三步:加间隙锁 :给 id <5 的间隙(如 (0,3)、(3,5))加间隙锁,防止其他事务在这个范围内插入新行;
- 最终触发的是Next-Key Lock(记录锁 + 间隙锁),而非单独的间隙锁或记录锁。
