第3章 事务隔离级别与 MVCC 实现
本章导入
事务与并发控制是数据库内核面试的必考核心。面试官关注你是否理解MVCC(多版本并发控制)的底层实现、锁与隔离级别的对应关系,以及实际排查死锁的工程经验。以下内容以“原理 + 实战”结构拆解高频问题,帮助你建立清晰的回答框架。
回答框架图:MVCC 实现可重复读
使用说明:回答任何 MVCC 原理问题时,按此框架展开,让面试官看到你有“定义→机制→对比→总结”的结构化思维。
问答卡片 1
面试问题:请解释 MySQL InnoDB 中 MVCC 是如何实现可重复读隔离级别的?
| 面试官考察点 |
|
| 回答框架 |
|
| 简短示例回答 | InnoDB 为每行维护多个版本(undo log)。事务在 RR 下第一次快照读时生成 ReadView,后续读取相同版本链,保证可重复读。例如事务 A 先 SELECT,事务 B 插入新行并提交,A 再次 SELECT 看不到新行,因为 ReadView 标记 B 为未提交。若 A 使用当前读(UPDATE),则会加 Next-Key Lock 阻止幻插入。 |
| 可能追问 |
|
| 避坑提醒 |
不要只说“MVCC 通过多版本实现可重复读”,缺少 ReadView 具体细节。也不要把 RR 下的快照读当作“全量快照”,实际只有第一次 SELECT 生成 ReadView。
|
问答卡片 2
面试问题:间隙锁(Gap Lock)与临键锁(Next-Key Lock)有什么区别?在什么场景下会触发?
| 面试官考察点 |
|
| 回答框架 |
|
| 简短示例回答 | Gap Lock 只锁索引记录之间的间隙,防止幻插入;Next-Key Lock 锁住记录及其前一个间隙。例如表 id 主键,RR 下执行 SELECT * FROM t WHERE id = 5 FOR UPDATE,若 id=5 存在则只加 Record Lock;若 id 不在,则加 Gap Lock 锁住 (prev, next) 间隙。 |
| 可能追问 |
|
| 避坑提醒 |
常见错误:认为 Gap Lock 和 Next-Key Lock 完全等价。注意 Next-Key Lock 是包含记录锁的“正区间”,而 Gap Lock 是开区间。另外,唯一索引等值命中时退化,不要忘记说明。
|
问答卡片 3
面试问题:如何排查死锁?请描述一次你实际处理死锁问题的经历。
| 面试官考察点 |
|
| 回答框架 |
|
| 简短示例回答 | 曾遇到转账场景死锁:事务 A 更新用户 1 后更新用户 2,事务 B 反向更新。死锁日志显示锁顺序交叉。我们统一按用户 ID 升序加锁,并增加唯一索引减少间隙锁冲突。测试后死锁消失,TPS 提升 15%。 |
| 可能追问 |
|
| 避坑提醒 |
面试官想看真实案例,不要编造。可以简化但需包含:发现方式、日志分析、根因、解决方案、效果指标。避免只说“我加了索引”,要说明加什么索引以及为什么。
|
知识结构表格:三种锁及其触发场景
| 锁类型 | 锁范围 | 触发场景 (RR 级别) | 作用 |
|---|---|---|---|
| Record Lock | 单条索引记录 | 唯一索引等值命中 | 避免行级修改冲突 |
| Gap Lock | 索引记录之间的间隙 | 非唯一索引扫描 / 范围查询 | 防止幻插入 |
| Next-Key Lock | 记录 + 前间隙 | RR 下默认的索引扫描锁 | 记录锁 + 间隙锁的组合 |
避坑总结
加分点:在回答锁和 MVCC 时,主动提到
information_schema.INNODB_TRX、SHOW ENGINE INNODB STATUS 等诊断命令,体现工程底蕴。对比 RC 与 RR 的行为差异时,使用“短事务 + 索引优化”等落地建议。