真实面经题目 · 原创解析
MySQL 支持哪些隔离级别,对应实现原理是什么?
考察 MySQL InnoDB 隔离级别、MVCC、ReadView、undo log 和锁机制,重点是快照读与当前读的实现差异。
真实面经题目 · 原创解析
考察 MySQL InnoDB 隔离级别、MVCC、ReadView、undo log 和锁机制,重点是快照读与当前读的实现差异。
MySQL 支持读未提交、读已提交、可重复读和串行化四个隔离级别。InnoDB 的普通快照读主要靠 MVCC 实现:记录有隐藏事务 ID 和回滚指针,undo log 形成历史版本链,ReadView 决定当前事务能看见哪个版本。读已提交通常每次语句生成新的 ReadView,可重复读通常事务内复用同一个 ReadView,所以能稳定看到同一快照。当前读不是读快照,而是读最新版本并加锁;在可重复读下,InnoDB 通过记录锁、间隙锁和 next-key lock 减少幻读。串行化更强,但并发度最低。
读未提交可能读到别人未提交的数据;读已提交避免脏读;可重复读让同一事务内多次快照读结果稳定;串行化通过更强锁约束把并发事务近似排队执行。
InnoDB 记录隐藏事务 ID 和回滚指针,旧版本保存在 undo log 版本链里。快照读不会直接加行锁,而是根据 ReadView 判断某个版本是否对当前事务可见,必要时沿版本链回溯。
读已提交下,每次一致性读通常创建新的 ReadView,所以同一事务中第二次查询可能看到其他事务刚提交的数据。可重复读下,事务内第一次快照读生成 ReadView 后复用,因此多次读保持一致。
select for update、update、delete、insert 等当前读要读最新已提交版本并加锁。记录锁锁住已有记录,间隙锁锁住索引记录之间的范围,next-key lock 是记录锁加间隙锁,用来限制范围内插入。
快照读在 RR 下通过复用 ReadView 避免同一事务内看到新插入记录;当前读的范围修改需要 next-key lock 防止其他事务插入匹配范围。不能简单说 RR 永远没有幻读,要说明快照读和当前读场景。
快照读读的是符合 ReadView 的历史可见版本,普通 select 通常如此;当前读读最新版本并加锁,例如 update、delete、select for update。两者解决并发问题的机制不同。
RC 通常每条一致性读语句生成新的 ReadView,所以能看到其他事务后续提交;RR 通常事务内第一次快照读生成后复用,所以同一事务内多次快照读稳定。
普通快照读靠同一个 ReadView 看不到后插入记录;涉及当前读和范围修改时,InnoDB 依赖 next-key lock 锁住记录和间隙,阻止其他事务插入匹配范围。
InnoDB 的行锁是加在索引记录上的。查询条件没有命中合适索引时,锁范围可能扩大,甚至扫描更多记录,导致并发性能下降。