Skip to content

面试速答(先看这里)

**一句话结论:**脏读指一个事务可以读取另一个事务未提交的数据,导致数据不 一致。

60秒标准回答:

在Innodb中,通过MVCC解决脏读和不可重复读,通过MVCC+间隙锁解决幻读的

脏读的解决。 脏读指一个事务可以读取另一个事务未提交的数据,导致数据不 一致。在读已提交(Read Committed)隔离级别下,事务只能读取到其他事务已经提交的数据版本。因此,如果一个事务在读取数据时,另一个事务已经修改了这些数据但尚未提交,那么读取事务将不会看到这些未提交的更改

脏 读的解决依赖了Read View,Read View会来告诉我们本次事务应该看到哪个快照,不应该看到哪个快照

**答题顺序:**结论 → 原理/机制 → 关键流程 → 场景与取舍 → 易错点

回答主线:

  • **要点1:**在Innodb中,通过MVCC解决脏读和不可重复读,通过MVCC+间隙锁解决幻读的。
  • **要点2:**脏 读的解决依赖了Read View,Read View会来告诉我们本次事务应该看到哪个快照,不应该看到哪个快照。
  • **要点3:**简单点说就是:当事务在“读已提交”隔离级别下执行读取操作时, InnoDB获取当前最新的全局事务ID,这个ID表示在当前时刻所有已提交事务的最新状态。
  • **要点4:**不可重读的解决。
  • **要点5:**InnoDB的RR级别中,基于MVCC+间隙锁,是在某种程度上是可以避免幻读的发生的,但是没有办法完全避免,当一个事务中发生当前读的时候,会导致幻读的发生。

**记忆锚点:**InnoDB → Read → MVCC+ → View → 间隙锁 → ReadView

易错提醒:

  • InnoDB的RR级别中,基于MVCC+间隙锁,是在某种程度上是可以避免幻读的发生的,但是没有办法完全避免,当一个事务中发生当前读的时候,会导致幻读的发生。

加分表达:

  • 因此,如果一个事务在读取数据时,另一个事务已经修改了这些数据但尚未提交,那么读取事务将不会看到这些未提交的更改。
  • InnoDB会检查每个数据行的版本,如果该版本是由一个小于或等于当前事务ID的事务修改的,并且该事务已提交,则这个版本是可见的。

追问准备:

  • 围绕「InnoDB」:底层原理是什么?使用时有哪些边界和常见坑?
  • 围绕「Read」:底层原理是什么?使用时有哪些边界和常见坑?
  • 围绕「MVCC+」:底层原理是什么?使用时有哪些边界和常见坑?
  • 如果线上出现异常,你会如何定位、验证并规避?

典型回答 ​

在Innodb中,通过MVCC解决脏读和不可重复读,通过MVCC+间隙锁解决幻读的。

**脏读的解决。**脏读指一个事务可以读取另一个事务未提交的数据,导致数据不一致。在读已提交(Read Committed)隔离级别下,事务只能读取到其他事务已经提交的数据版本。因此,如果一个事务在读取数据时,另一个事务已经修改了这些数据但尚未提交,那么读取事务将不会看到这些未提交的更改。

脏读的解决依赖了Read View,Read View会来告诉我们本次事务应该看到哪个快照,不应该看到哪个快照。

📄 ✅什么是ReadView,什么样的ReadView可见?

打开文档:✅什么是ReadView,什么样的ReadView可见?

简单点说就是:当事务在“读已提交”隔离级别下执行读取操作时, InnoDB获取当前最新的全局事务ID,这个ID表示在当前时刻所有已提交事务的最新状态。InnoDB会检查每个数据行的版本,如果该版本是由一个小于或等于当前事务ID的事务修改的,并且该事务已提交,则这个版本是可见的。这保证了事务只能看到在它开始之前已经提交的数据版本。

**不可重读的解决。**不可重复读指一个事务读取同一行数据两次,但是在两次读取之间另一个事务修改了该行数据,导致两次读取的结果不同。InnoDB 通过使用 MVCC 来解决不可重复读的问题。在RR这种隔离级别下,当我们使用快照读进行数据读取的时候,只会在第一次读取的时候生成一个Read View,后续的所有快照读都是用的同一个快照,所以就不会发生不可重复读的问题了。

**幻读的解决。**InnoDB的RR级别中,基于MVCC+间隙锁,是在某种程度上是可以避免幻读的发生的,但是没有办法完全避免,当一个事务中发生当前读的时候,会导致幻读的发生。详情参考:

📄 ✅Innodb的RR到底有没有解决幻读?

打开文档:✅Innodb的RR到底有没有解决幻读?

总结下:

读现象解决方式
脏读每次查询生成新 ReadView,读取已提交的最新版本。
不可重复读事务开始时生成 ReadView,后续所有读操作基于此视图。
幻读MVCC+间隙锁可解决一部分,另外就是需要强制加锁,所有操作串行执行。