外观
MVCC 的作用
⭐ 题目日期:
阿里 - 2024/8/21
📝 题解:
MVCC(多版本并发控制,Multi-Version Concurrency Control) 是数据库管理系统(如 MySQL InnoDB、PostgreSQL)中实现高并发访问的核心技术。它通过维护数据的多个版本来避免读写操作之间的冲突,从而在不加锁的情况下保证事务的隔离性,显著提升并发性能。
MVCC 的核心作用
1. 实现无锁读操作(Non-Locking Read)
- 读写不阻塞:读操作不会阻塞写操作,写操作也不会阻塞读操作。
例如:事务 A 在读取数据时,事务 B 仍可修改同一数据,两者互不影响。 - 避免锁竞争:传统锁机制(如行锁)会导致大量线程等待,MVCC 通过多版本机制减少锁争用。
2. 支持事务隔离级别
- 读已提交(Read Committed):读取其他事务已提交的最新数据。
- 可重复读(Repeatable Read)(InnoDB 的默认隔离级别):事务内多次读取同一数据时,结果一致(基于事务开始的快照)。
- 解决脏读、不可重复读问题,但无法完全解决幻读(需结合间隙锁)。
3. 基于版本链的并发控制
- 数据版本链:每一行数据隐含两个字段(
DB_TRX_ID
和DB_ROLL_PTR
):DB_TRX_ID
:最后修改该数据的事务 ID。DB_ROLL_PTR
:指向 undo log 中旧版本数据的指针,形成版本链。
- 快照读(Snapshot Read):事务读取时,基于版本链选择可见的数据版本(由事务 ID 和活跃事务列表决定)。
MVCC 的实现原理
1. 数据版本管理
- 插入/更新操作:
修改数据时,旧版本数据会存入 undo log,新版本通过DB_ROLL_PTR
指向旧版本,形成版本链。 - 删除操作:
标记数据为删除状态,实际数据在版本链中保留,直到无事务需要访问旧版本。
2. 可见性判断(ReadView)
- 事务首次读取数据时生成 ReadView,记录当前活跃事务 ID 列表。
- 根据以下规则判断数据版本是否可见:
- 如果数据版本的
DB_TRX_ID
小于当前事务 ID,且不在活跃事务列表中 → 可见。 - 如果数据版本的
DB_TRX_ID
是当前事务自身的 ID → 可见。 - 其他情况 → 不可见,需沿版本链查找更旧的版本。
- 如果数据版本的
MVCC 的优缺点
优点
- 高并发:读写操作互不阻塞,适合读多写少的场景。
- 一致性快照:事务读取的数据基于时间点快照,保证可重复读。
- 减少锁开销:避免频繁加锁,提升吞吐量。
缺点
- 存储开销:需维护多版本数据和 undo log,占用额外空间。
- 历史数据清理:旧版本数据需在无事务访问后由 purge 线程清理。
MVCC 在 InnoDB 中的实践
- 隔离级别支持:
- 读已提交(RC):每次读取生成新 ReadView,看到已提交的最新数据。
- 可重复读(RR):事务内首次读取生成 ReadView,后续复用该视图,保证一致性。
- 与锁的协同:
MVCC 处理读操作,写操作仍会加锁(如行锁、间隙锁)保证写并发安全。
示例场景
- 事务 A 读取数据:
- 生成 ReadView,找到版本链中符合可见性规则的数据。
- 事务 B 修改数据:
- 写入新版本并更新
DB_TRX_ID
,旧版本存入 undo log。
- 写入新版本并更新
- 事务 A 再次读取:
- RR 隔离级别下,仍读取旧版本(ReadView 未更新);RC 级别下读取新版本(生成新 ReadView)。
总结
MVCC 通过多版本数据链和快照读机制,在保证事务隔离性的同时,极大提升了数据库的并发性能。它是实现高并发、高响应数据库系统的关键技术,也是 InnoDB 默认隔离级别(可重复读)的基石。