Skip to content

MVCC 的作用

约 991 字大约 3 分钟

MySQL阿里

2025-4-7

⭐ 题目日期:

阿里 - 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_IDDB_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 列表。
  • 根据以下规则判断数据版本是否可见:
    1. 如果数据版本的 DB_TRX_ID 小于当前事务 ID,且不在活跃事务列表中 → 可见。
    2. 如果数据版本的 DB_TRX_ID 是当前事务自身的 ID → 可见。
    3. 其他情况 → 不可见,需沿版本链查找更旧的版本。

MVCC 的优缺点

优点

  • 高并发:读写操作互不阻塞,适合读多写少的场景。
  • 一致性快照:事务读取的数据基于时间点快照,保证可重复读。
  • 减少锁开销:避免频繁加锁,提升吞吐量。

缺点

  • 存储开销:需维护多版本数据和 undo log,占用额外空间。
  • 历史数据清理:旧版本数据需在无事务访问后由 purge 线程清理。

MVCC 在 InnoDB 中的实践

  • 隔离级别支持
    • 读已提交(RC):每次读取生成新 ReadView,看到已提交的最新数据。
    • 可重复读(RR):事务内首次读取生成 ReadView,后续复用该视图,保证一致性。
  • 与锁的协同
    MVCC 处理读操作,写操作仍会加锁(如行锁、间隙锁)保证写并发安全。

示例场景

  1. 事务 A 读取数据
    • 生成 ReadView,找到版本链中符合可见性规则的数据。
  2. 事务 B 修改数据
    • 写入新版本并更新 DB_TRX_ID,旧版本存入 undo log。
  3. 事务 A 再次读取
    • RR 隔离级别下,仍读取旧版本(ReadView 未更新);RC 级别下读取新版本(生成新 ReadView)。

总结

MVCC 通过多版本数据链和快照读机制,在保证事务隔离性的同时,极大提升了数据库的并发性能。它是实现高并发、高响应数据库系统的关键技术,也是 InnoDB 默认隔离级别(可重复读)的基石。