侧边栏壁纸
博主头像
牧云

怀璧慎显,博识谨言。

  • 累计撰写 217 篇文章
  • 累计创建 20 个标签
  • 累计收到 8 条评论

目 录CONTENT

文章目录

InnoDB 的锁机制(Next-Key Lock)结合 MVCC 不能彻底解决幻读问题

秋之牧云
2026-07-13 / 0 评论 / 0 点赞 / 2 阅读 / 0 字

InnoDB 的锁机制(Next-Key Lock)结合 MVCC 不能彻底解决幻读问题,只能在很大程度上避免 。虽然这两种机制分别针对快照读和当前读解决了绝大部分幻读场景,但在特定混合操作下仍会出现幻读现象

1. 解决幻读的两种核心机制

在可重复读(Repeatable Read, RR)隔离级别下,InnoDB 通过以下方式规避幻读:

  • 快照读(Snapshot Read): 普通的 SELECT 语句通过 MVCC 机制解决幻读。事务在首次查询时生成 Read View,后续查询均基于该视图读取历史版本数据,因此其他事务的新增记录对当前事务不可见
  • 当前读(Current Read): SELECT ... FOR UPDATEUPDATEDELETE 等操作通过 Next-Key Lock(记录锁 + 间隙锁)解决幻读。该锁机制不仅锁定现有记录,还锁定索引间隙,阻止其他事务在范围内插入新记录,从而避免幻读

2. 无法彻底解决幻读的场景

尽管上述机制有效,但在以下特殊场景中,RR 级别依然会发生幻读:

  • 快照读后执行当前读: 如果事务先进行了一次普通 SELECT(快照读),随后另一事务插入数据并提交,此时原事务若执行 SELECT ... FOR UPDATE(当前读),则会读取到最新提交的数据。由于当前读不使用 MVCC 快照且新数据不在原有快照中,导致前后两次查询结果不一致,产生幻读
  • 快照读后更新新插入的记录: 事务 A 先进行快照读,事务 B 插入一条符合查询条件的记录并提交。若事务 A 随后执行 UPDATE 修改了这条新记录,该记录会被“激活”并对事务 A 可见。此时事务 A 再次进行快照读,会发现结果集中多了一条数据,从而引发幻读
  • 范围锁的局限性: Next-Key Lock 只能锁定已存在的索引范围,在某些边界条件或无索引列的全表扫描场景下,可能无法完全覆盖所有潜在的插入点

3. 如何彻底解决幻读

若要完全杜绝幻读,需采用以下方案:

  • 串行化隔离级别(Serializable): 强制所有读写操作加锁,使事务串行执行,这是唯一能彻底解决幻读的方法,但会显著降低并发性能
  • 应用层控制: 在 RR 级别下,开发者需手动确保事务一开始就使用当前读(如 SELECT ... FOR UPDATE)而非快照读,以触发 Next-Key Lock 保护,但这增加了开发复杂度且仍有边缘风险

综上所述,InnoDB 在 RR 级别下的 MVCC 和 Next-Key Lock 组合是工程上的权衡方案,旨在平衡一致性与性能,而非理论上的完美解决方案

0

评论区