MySQL MVCC 实现原理
一、MVCC 是什么?
MVCC(Multi-Version Concurrency Control,多版本并发控制)是数据库管理系统常用的一种并发控制方法,旨在提高读写并发性能,避免读写操作相互阻塞。
二、实现原理
MVCC 的实现主要依赖以下三个核心组件:
1. 隐藏字段
每一行记录除了用户定义的列,还有三个隐藏列:
- DB_TRX_ID:最近修改该行记录的事务 ID。
- DB_ROLL_PTR:回滚指针,指向该行上一个版本的 undo 日志记录,用于构建版本链。
- DB_ROW_ID:隐含的自增 ID(如果表没有主键,InnoDB 会用它来组织聚簇索引)。
2. Undo Log 日志
- 当一行记录被修改时,InnoDB 会将旧的一整行记录包括隐藏字段写入 Undo Log,并通过 DB_ROLL_PTR 将新版本与旧版本链接起来,形成版本链。
- 版本链的头节点就是当前记录(最新版本),后续版本通过回滚指针找到。
3. Read View(读视图)
Read View 是事务执行快照读时生成的'快照',它记录了系统中活跃的事务 ID 列表(即尚未提交的事务)。通过 Read View,可以判断版本链中的哪个版本对当前事务是可见的。隔离级别 读已提交(Read Committed)就是通过这个来判断的。
Read View 主要包含:
- m_low_limit_id:高水位,大于等于该值的所有事务 ID 均不可见。(注:事务 ID 是自增的,m_low_limit_id = 当前系统已有最大事务 ID + 1,如果出现 id >= m_low_limit_id 说明生成 ReadView 时这个 id 对应的事务还没开启,所以这行记录不可见)
- m_up_limit_id:低水位,活跃事务 ID 列表中的最小 id,小于该值的事务 ID 均可见(已提交)。
- m_ids:活跃事务 ID 列表,即生成 Read View 时尚未提交的事务集合。m_up_limit_id < id < m_low_limit_id,且 id 不在活跃事务 ID 列表则可见。
示例
假设当前系统已有事务 ID 1、2、3、4、5。生成 Read View 时:
- 活跃事务:3、5(尚未提交)
- 已提交事务:1、2、4
- 下一个事务 ID 为 6
则:
m_up_limit_id= 3m_low_limit_id= 6m_ids= [3, 5]
可见性判断:
- 版本的事务 ID = 1 → < 3 → 已提交 → 可见
- 版本的事务 ID = 2 → < 3 → 已提交 → 可见
- 版本的事务 ID = 3 → 在
m_ids中 → 尚未提交 → 不可见 - 版本的事务 ID = 4 → 在
[3,6)范围内且不在m_ids→ 已提交 → 可见 - 版本的事务 ID = 5 → 在
m_ids中 → 不可见 - 版本的事务 ID = 6 → ≥ 6 → 尚未开始 → 不可见
即使事务 6 在生成 Read View 后立即提交,它对当前事务仍然不可见,因为快照中不包含它。


