温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

MVCC在MySQL中怎实现

发布时间:2026-09-09 21:45:04 来源:亿速云 阅读:104 作者:小樊 栏目:数据库

MySQL(以 InnoDB 存储引擎为例)中,MVCC(Multi-Version Concurrency Control,多版本并发控制) 是通过 隐藏字段 + Undo Log + Read View 三者配合实现的,用来在“不加锁”的情况下实现高并发读写。

下面按「是什么 → 怎么存 → 怎么读 → 怎么判断可见性」来讲。


一、MVCC 解决什么问题?

MVCC 主要解决:

  • 读写不阻塞(读不阻塞写,写不阻塞读)
  • 实现 可重复读(REPEATABLE READ)读已提交(READ COMMITTED)
  • 避免大量加锁带来的性能问题

二、InnoDB 中 MVCC 的核心组成

1️⃣ 每行记录的「隐藏字段」

InnoDB 每行数据都有隐藏列:

隐藏字段 作用
DB_TRX_ID 最后修改该行的事务 ID
DB_ROLL_PTR 回滚指针,指向 Undo Log 中的旧版本
DB_ROW_ID 行ID(无主键时用于聚簇索引)

2️⃣ Undo Log(版本链)

每次更新数据:

  • 旧数据写入 Undo Log
  • 新数据行通过 DB_ROLL_PTR 指向旧版本

于是形成 版本链

最新版本
  ↓ roll_ptr
旧版本1
  ↓ roll_ptr
旧版本2
  ↓
...

3️⃣ Read View(读视图)

Read View 是事务在「读数据时」生成的一个快照,用于判断:

当前事务能看到哪个版本的数据?

Read View 包含:

  • 当前活跃事务 ID 列表
  • 最小事务 ID
  • 下一个将分配的事务 ID

三、MVCC 读数据的过程(核心)

示例场景

事务 A(ID=10)读取一行数据
此时事务 B(ID=20)正在修改但未提交

判断规则(简化版)

对每一行版本:

  1. 如果 DB_TRX_ID < 最小活跃事务 ID
    ✅ 已提交,可见
  2. 如果 DB_TRX_ID 在活跃事务列表中
    ❌ 未提交,不可见
  3. 顺着 DB_ROLL_PTR 找上一个版本,继续判断

永远读不到未提交的数据


四、不同隔离级别下的 MVCC 行为

隔离级别 Read View 生成时机
READ COMMITTED 每次 SELECT 都生成
REPEATABLE READ 第一次 SELECT 时生成(默认)
SERIALIZABLE 直接加锁,不用 MVCC

✅ MySQL 默认是 REPEATABLE READ,靠 MVCC 实现


五、MVCC 不能解决什么?

MVCC 不解决

  • 写写冲突(仍需锁)
  • 幻读(InnoDB 用 Next-Key Lock 补上)

六、一句话总结

MySQL 的 MVCC =
每行多版本(Undo Log) + 事务快照(Read View) + 可见性规则

如果你愿意,我也可以:

  • 画一张 MVCC 版本链示意图
  • 用具体 SQL 演示 MVCC 过程
  • 对比 MVCC 和锁机制的区别
向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI