mysql 中mvcc 原理是什么?用了什么数据结构?
MVCC 通过隐藏事务信息、undo 历史版本和一致性读可见性规则工作,不应被简化成只有一个 Read View 数据结构。
直接结论
InnoDB 的 MVCC 让一致性读在不对所读记录加普通共享锁的情况下看到适合当前事务的历史版本。聚簇记录包含事务相关隐藏字段,旧版本信息由 undo 记录串联;一致性读根据事务隔离级别和读视图判断某个版本是否可见。Read View 是可见性判断的一部分,而不是 MVCC 的全部数据结构。普通 SELECT 的一致性读与 SELECT ... FOR UPDATE、UPDATE 等当前读也必须区分。
原理与步骤
记录被修改时会产生可用于重建旧版本的 undo 信息,并记录修改事务标识。一致性读需要判断版本由哪个事务产生、该事务在快照边界下是否已提交且可见;不可见时沿 undo 信息查找更早版本。READ COMMITTED 通常每次一致性读建立新的读取视图,REPEATABLE READ 通常在事务内首次一致性读时形成并复用快照,因此两次读取观察结果可能不同。长事务会阻碍历史版本清理,使 undo 和存储压力上升。
工程场景
报表查询若在 REPEATABLE READ 长事务中持续数小时,能保持一致视图,却可能让更新频繁表积累大量历史版本;工程上应缩短事务、避免交互期间持有事务,并监控历史列表和清理进度。余额扣减不能靠快照读后在应用层判断,应使用带条件的原子 UPDATE、锁定读或适合的事务设计。排查“为什么看不到刚提交数据”时,先确认隔离级别、事务是否已开始一致性读以及查询是否属于当前读。
验证与边界
MVCC 不等于没有锁:写写冲突、锁定读、唯一性检查和外键检查仍会使用锁。它也不能单独消除所有幻读语义,需结合隔离级别与 InnoDB 锁策略。undo 不是无限保留,版本可见性也不是把整行复制在内存 Read View 中。验证可用两个连接控制提交顺序,在 READ COMMITTED 与 REPEATABLE READ 下重复相同 SELECT,并观察当前读差异;结论应绑定 MySQL/InnoDB 版本和官方隔离语义。
答题练习
- 1隐藏事务字段与 undo 版本
- 2读视图决定一致性读可见性
- 3不同隔离级别创建视图时点不同
常见错误
- 把 MVCC 等同于 Read View 一个对象
- 认为 MVCC 场景完全不加锁
可能追问
- 长事务为何影响 purge
- 一致性读和当前读有何差异
来源记录
- 原始来源
- 小林coding
- 来源页面
- 上海银行 Java 面试
- 最近收录
- 2026-07-05
- 官方复核
- MySQL 官方文档