60 秒回答模板

MySQL 支持读未提交、读已提交、可重复读和串行化四个隔离级别。InnoDB 的普通快照读主要靠 MVCC 实现:记录有隐藏事务 ID 和回滚指针,undo log 形成历史版本链,ReadView 决定当前事务能看见哪个版本。读已提交通常每次语句生成新的 ReadView,可重复读通常事务内复用同一个 ReadView,所以能稳定看到同一快照。当前读不是读快照,而是读最新版本并加锁;在可重复读下,InnoDB 通过记录锁、间隙锁和 next-key lock 减少幻读。串行化更强,但并发度最低。

考点 核心机制与工程取舍
难度 中高频面试题
回答目标 按定义、机制、场景讲清楚

深入解析

01

四个隔离级别

读未提交可能读到别人未提交的数据;读已提交避免脏读;可重复读让同一事务内多次快照读结果稳定;串行化通过更强锁约束把并发事务近似排队执行。

02

MVCC 负责快照读

InnoDB 记录隐藏事务 ID 和回滚指针,旧版本保存在 undo log 版本链里。快照读不会直接加行锁,而是根据 ReadView 判断某个版本是否对当前事务可见,必要时沿版本链回溯。

03

RC 与 RR 的核心差异

读已提交下,每次一致性读通常创建新的 ReadView,所以同一事务中第二次查询可能看到其他事务刚提交的数据。可重复读下,事务内第一次快照读生成 ReadView 后复用,因此多次读保持一致。

04

当前读依赖锁

select for update、update、delete、insert 等当前读要读最新已提交版本并加锁。记录锁锁住已有记录,间隙锁锁住索引记录之间的范围,next-key lock 是记录锁加间隙锁,用来限制范围内插入。

05

幻读要区分语义

快照读在 RR 下通过复用 ReadView 避免同一事务内看到新插入记录;当前读的范围修改需要 next-key lock 防止其他事务插入匹配范围。不能简单说 RR 永远没有幻读,要说明快照读和当前读场景。

易错点

  • 只背四个隔离级别,不讲 MVCC、ReadView 和锁如何实现。
  • 把所有 select 都说成会加锁,混淆快照读和当前读。
  • 绝对化说 RR 完全没有幻读,不区分快照读和当前读。
  • 忽略索引对 next-key lock 范围和并发性能的影响。

面试官追问

快照读和当前读有什么区别?

快照读读的是符合 ReadView 的历史可见版本,普通 select 通常如此;当前读读最新版本并加锁,例如 update、delete、select for update。两者解决并发问题的机制不同。

RC 和 RR 的 ReadView 区别是什么?

RC 通常每条一致性读语句生成新的 ReadView,所以能看到其他事务后续提交;RR 通常事务内第一次快照读生成后复用,所以同一事务内多次快照读稳定。

InnoDB RR 为什么还能处理幻读?

普通快照读靠同一个 ReadView 看不到后插入记录;涉及当前读和范围修改时,InnoDB 依赖 next-key lock 锁住记录和间隙,阻止其他事务插入匹配范围。

为什么索引会影响锁范围?

InnoDB 的行锁是加在索引记录上的。查询条件没有命中合适索引时,锁范围可能扩大,甚至扫描更多记录,导致并发性能下降。