ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

理解 MVCC:多版本并发控制原理详解

理解 MVCC:多版本并发控制原理详解 1. 什么是 MVCCMVCCMulti-Version Concurrency Control多版本并发控制是一种数据库并发控制机制其核心思想是在读写并发场景下读操作不阻塞写操作写操作也不阻塞读操作。它通过为数据维护多个历史版本让不同事务看到不同时间点的数据快照从而在保证事务隔离性的同时大幅提升数据库的并发性能。MVCC 是现代主流关系型数据库如 MySQL InnoDB、PostgreSQL、Oracle以及部分 NoSQL 数据库如 TiDB实现高并发读写的基石。它主要解决的是读写冲突问题而不是写写冲突——两个事务同时修改同一行数据时仍然需要通过锁机制如行锁来保证正确性。2. 为什么需要 MVCC在数据库并发访问中如果不加任何控制会出现脏读、不可重复读、幻读等问题。传统的解决方案是加锁读锁和写锁互斥但这会导致读操作被写操作阻塞在高并发场景下严重降低系统吞吐量。MVCC 的巧妙之处在于读操作读取的是某个时间点的快照而不是当前正在被修改的数据。这样一来读操作无需等待写操作释放锁写操作也无需等待读操作完成读写可以并行执行从而显著提升并发能力。3. MVCC 的核心组成MVCC 的实现通常依赖三个核心组成部分隐藏列、Undo 日志回滚日志和 Read View读视图。下面逐一说明。3.1 隐藏列InnoDB 会在每行数据后添加两个隐藏列实际还有删除标记位DB_TRX_ID记录最近一次修改该行数据的事务 ID。DB_ROLL_PTR回滚指针指向 Undo 日志中该行历史版本的地址通过它可以串联起该行的版本链。3.2 Undo 日志当某事务修改一行数据时InnoDB 会先把修改前的旧值写入 Undo 日志然后通过回滚指针将新版本与旧版本串联起来形成一条版本链。版本链的头部是最新版本越往链尾越是历史版本。3.3 Read ViewRead View 是事务执行快照读时生成的一个视图它记录了当前系统中活跃事务尚未提交的事务的 ID 列表。通过 Read View事务可以判断版本链中哪个版本对它可见。4. MVCC 原理可见性判断当一个事务执行快照读时会沿着版本链从新到旧逐个判断每个版本的可见性。判断规则如下假设当前事务 ID 为trx_idRead View 中记录的信息包括m_ids生成 Read View 时系统中活跃事务 ID 的集合。min_trx_id活跃事务中最小的 ID。max_trx_id生成 Read View 时系统已分配的最大事务 ID 1。creator_trx_id生成该 Read View 的事务自己的 ID。对于版本链中某个版本的DB_TRX_ID可见性判断逻辑如下若DB_TRX_ID creator_trx_id说明该版本是当前事务自己修改的可见。若DB_TRX_ID min_trx_id说明该版本在 Read View 生成前已提交可见。若DB_TRX_ID max_trx_id说明该版本是 Read View 生成之后才产生的事务修改的不可见。若min_trx_id DB_TRX_ID max_trx_id则判断DB_TRX_ID是否在m_ids中若在说明该事务尚未提交不可见若不在说明该事务已提交可见。如果当前版本不可见则通过回滚指针沿版本链继续向前查找直到找到可见版本或到达链尾。5. 快照读与当前读MVCC 将读操作分为两类理解它们的区别至关重要5.1 快照读快照读读取的是事务开始时的快照数据不加锁是普通的SELECT语句。在可重复读隔离级别下快照读基于 Read View 实现同一事务多次读取结果一致从而避免了不可重复读问题。5.2 当前读当前读读取的是数据的最新版本并且会加锁包括SELECT ... FOR UPDATE、UPDATE、DELETE等操作。当前读读取的是最新已提交的数据因此不受 MVCC 快照的保护。6. MVCC 与隔离级别的关系MVCC 主要服务于两个隔离级别读已提交Read Committed和可重复读Repeatable Read。两者的区别在于 Read View 的生成时机读已提交每次执行快照读时都会生成一个新的 Read View因此同一事务内多次读取可能看到不同数据存在不可重复读问题。可重复读只在第一次执行快照读时生成 Read View后续所有快照读都复用该视图因此同一事务内多次读取结果一致解决了不可重复读问题。MVCC 无法彻底解决幻读问题。在可重复读级别下InnoDB 通过间隙锁Gap Lock与 MVCC 配合才基本解决了幻读。7. 总结MVCC 通过为数据维护多版本并结合 Read View 的可见性判断实现了读写不互斥的高并发模型。它的核心价值在于在不使用昂贵锁的前提下让读操作获得一致性的快照同时保证写操作可以并行进行。理解 MVCC 的版本链、隐藏列和 Read View 机制是深入掌握数据库事务隔离与并发控制的关键。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进