MVCC 多版本并发控制

通过保存数据的历史版本让读操作不阻塞写、写不阻塞读;不同隔离级别对应不同快照规则,长事务与热点更新会造成版本堆积,需要清理机制。

MVCC 是什么

MVCC(多版本并发控制)通过保存数据的历史版本让读操作不阻塞写、写不阻塞读:每个事务看到的是某个时间点的可见版本,旧版本由撤销日志或旧行保留,由后台机制清理。不同隔离级别对应不同的快照规则,因此同一份数据在不同事务中可能看到不同内容。它的主要代价是版本堆积与清理压力,长事务与热点更新是常见诱因。

基本信息

核心机制每个事务看到某一时间点的可见版本,旧版本保留供并发读
典型实现PostgreSQL 的行版本与 VACUUM;InnoDB 的 undo log 与 purge
运维关注长事务、快照过老、清理滞后导致空间膨胀
读写关系普通读不加锁,写与写之间仍需要锁或冲突检测
代价存储与清理开销上升,复制与备份需考虑版本信息

常见现象与对策

现象原因对策
表空间持续增长旧版本未被及时清理排查长事务,检查清理参数与调度
查询返回旧数据事务快照建立较早缩短事务范围,避免事务中等待用户输入
更新热点行失败写写冲突或锁等待超时缩短持有时间,考虑拆分行或异步化
清理进度落后长事务阻塞回收设置事务超时,监控最老快照年龄

典型使用场景

  • 高并发读场景:读请求不阻塞写入,吞吐显著提升
  • 报表与导出:需要在一致快照上运行较长时间的查询
  • 长事务治理:识别并限制长时间持有快照的事务
  • 数据库调优:分析空间膨胀与清理滞后的根因
  • 并发问题排查:理解同一行在不同事务中为何看到不同值
  • 架构评审:判断业务是否依赖“读到最新值”,据此选择隔离级别
MVCC 解决的是读写冲突,不解决写写冲突:同一行并发更新仍需要锁、乐观锁版本号或条件更新来保证正确性。
长事务持有老快照会让清理机制无法推进,表与索引持续膨胀,最终影响整个实例的性能。

易错点

  • 长事务持有老快照,清理无法推进导致表与索引膨胀
  • 把 MVCC 当万能解,忽略写写冲突仍需锁或重试
  • 事务中等待用户输入或远程调用,事务时长不可控,快照长期占用
  • 认为普通读不加锁就一定读到最新数据,业务逻辑按错误假设编写
  • 未监控最老快照年龄与清理延迟,空间膨胀到磁盘告警才发现

数据来源与参考

  • PostgreSQL 文档:Concurrency Control(MVCC)
  • MySQL 8.0 Reference Manual:InnoDB Multi-Versioning
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌