Skip to Content
面试题库Mysql[面试题] InnoDB 的 RR 级别到底有没有解决幻读?

[面试题] InnoDB 的 RR 级别到底有没有解决幻读?

📖 版块 A:知识讲解版 (温故知新)

  • 基本定义

    • 幻读:在一个事务内,多次执行同一查询,由于其他事务插入了新行,导致后续查询结果集中出现了之前未见的行。
    • RR (Repeatable Read):可重复读,是 MySQL InnoDB 的默认隔离级别。
  • InnoDB 的应对机制

    1. 快照读 (Snapshot Read):普通的 SELECT 查询。通过 MVCC (多版本并发控制) 实现。事务启动时生成一个 Read View,整个事务期间看到的都是这个一致性视图,从而规避了幻读。
    2. 当前读 (Current Read)SELECT ... FOR UPDATEUPDATEDELETE 等。通过 Next-Key Locks (记录锁 + 间隙锁) 实现。在扫描到的索引记录上加记录锁,在间隙上加间隙锁,防止其他事务在间隙中插入新数据。
  • 核心结论

    • 完全使用快照读完全使用当前读的情况下,InnoDB 解决了幻读。
    • 但在快照读与当前读混用的特殊边缘场景下,依然可能出现幻读。

🎤 版块 B:面试实战版 (高手逐字稿)

Q:InnoDB 的 RR 级别到底有没有解决幻读?

🧠 破局思路:这是一个典型的“陷阱题”。面试官不希望听到简单的“解决了”或“没解决”,而是想考察你是否理解 InnoDB 存储引擎中 MVCC间隙锁 (Gap Lock) 的配合机制。破局的关键在于区分“快照读”和“当前读”两种场景,并点出那个极少数能触发幻读的“边缘逻辑”。

💬 高手逐字稿

关于 InnoDB 是否解决了幻读,我的理解是:它在绝大部分应用场景下解决了幻读,但并没有从物理上完全消除所有可能发生幻读的边缘情况。

首先,我们需要把读取方式拆分为“快照读”和“当前读”来看。

对于快照读(也就是普通的 SELECT),InnoDB 是通过 MVCC(多版本并发控制)来解决幻读的。事务在开启后第一次执行查询时会生成一个 Read View,之后整个事务中的查询都基于这个视图,即使其他事务插入了新数据,当前事务也看不到,从而保证了数据的一致性。

对于当前读(比如 SELECT ... FOR UPDATEUPDATE 语句),InnoDB 是通过 Next-Key Locks 来解决幻读的。Next-Key Locks 结合了行锁和间隙锁(Gap Lock)。当事务执行当前读时,它不仅会锁住现有的记录,还会把索引记录之间的“间隙”锁住,导致其他事务无法在这些间隙中插入新数据,从根本上杜绝了幻读的产生。

但是,这里有一个高手容易关注到的细节:如果在一个事务中,快照读和当前读混合使用,幻读仍有可能发生。

举个例子:事务 A 先执行一次普通的快照读,发现没有某行记录。此时事务 B 插入并提交了这行记录。接着事务 A 并不是再次查询,而是执行了一次 UPDATE 语句,恰好更新到了事务 B 刚刚插入的那行数据。由于 UPDATE 是当前读,它会把这行新数据的 DB_TRX_ID 改为事务 A 的 ID。此时,事务 A 再进行快照读,这行原本不存在的数据就会莫名其妙地出现在结果集中。这就是 RR 级别下由于“权限提升”导致的幻读。

所以总结来说:InnoDB 通过 MVCC 和 Next-Key Lock 在各自的场景下极大地缓解了幻读问题,满足了绝大多数业务需求。但在事务内逻辑处理不当(如先查再改再查)时,幻读的隐患依然存在。


最后更新于:
⏱️

登录后开始阅读

当前 MVP 版本只开放邮箱密码登录注册。完成登录后即可进入面试题内容。

还没有账号?先去注册