MySQL--MVCC

1. 什么是 MVCC?

  • MVCC (Multi-Version Concurrency Control,多版本并发控制)

  • 核心思想:通过保存数据的多个版本,让读操作无需阻塞写操作,从而实现 高并发下的读写一致性

  • MVCC 主要用来实现:

    • 一致性读(Consistent Read,快照读)

    • 非阻塞读(读不加锁)

👉 MVCC 是 InnoDB 实现 事务隔离性(Isolation) 的关键机制。


2. MVCC 依赖的机制

(1) 隐藏字段

InnoDB 在每行数据后面都会存储一些隐藏字段:

  • DB_TRX_ID:最近修改该行的事务 ID

  • DB_ROLL_PTR:回滚指针,指向 Undo Log(用于找到之前版本的数据)

  • DB_ROW_ID:自增 ID(如果没有主键时生成)

(2) Undo Log

  • 作用:保存数据的旧版本,用于回滚 & MVCC 提供历史版本。

  • 每次 UPDATE/DELETE 都会生成对应的 Undo Log 记录旧值。

  • 链表结构:通过 DB_ROLL_PTR 串联起来,形成一条数据的版本链。

(3) Read View

  • Read View = 一致性视图,用于判断当前事务能看到哪些版本。

  • 在事务执行 快照读 时生成,包含以下关键字段:

    • m_ids:系统当前活跃事务 ID 列表

    • min_trx_id:活跃事务的最小 ID

    • max_trx_id:下一个将分配的事务 ID(未分配,意味着比它大的事务还没开始)

    • creator_trx_id:创建该 Read View 的事务 ID

👉 Read View 决定了 可见性规则


3. MVCC 的可见性规则

当事务执行 快照读 时,判断某个版本是否可见的逻辑:

设数据版本的 DB_TRX_ID = X

  1. 如果 X < min_trx_id → 表示事务已经提交 → 可见

  2. 如果 X ≥ max_trx_id → 表示事务还没开始 → 不可见

  3. 如果 min_trx_id ≤ X < max_trx_id → 表示事务可能在活跃中:

    • 如果 X ∈ m_ids(活跃事务列表) → 不可见(因为还没提交)

    • 如果 X ∉ m_ids → 可见(说明已经提交了)


4. 快照读 vs 当前读

  • 快照读(Snapshot Read)

    • SELECT * FROM table WHERE ...;

    • 不加锁,读取 Read View 可见的版本

    • 使用 MVCC 保证一致性

  • 当前读(Current Read)

    • SELECT ... FOR UPDATE / SELECT ... LOCK IN SHARE MODE

    • UPDATE / DELETE / INSERT

    • 读取最新版本,并且对数据加锁,防止并发修改

👉 总结:快照读 → MVCC 机制; 当前读 → 加锁机制。


5. MVCC 与事务隔离级别

  • 读未提交(Read Uncommitted)

    • 不使用 MVCC,直接读最新版本,可能产生脏读。

  • 读已提交(Read Committed)

    • 每次执行 SELECT 都生成新的 Read View。(和可重复读不同的关键点)

    • 只能看到已提交事务的数据,避免脏读。

    • 但会产生 不可重复读

  • 可重复读(Repeatable Read,InnoDB 默认)

    • 在事务第一次 SELECT 时生成 Read View,整个事务期间都使用这个快照。(和读已提交不同的关键点)

    • 避免脏读、不可重复读。

    • 但会有 幻读 → 通过 间隙锁(Gap Lock) 解决。

  • 串行化(Serializable)

    • 不用 MVCC,所有读写都加锁,效率最低。


6. 一个更新操作下的 MVCC 示例

假设有一行数据:id=1, name="Tom"

  • T1:事务 A 更新 name="Jerry"

    • 在 Undo Log 中保存旧版本 "Tom"

    • DB_TRX_ID = A

  • T2:事务 B 开始,生成 Read View(活跃事务包含 A)

    • B 执行 SELECT name FROM user WHERE id=1;

    • 判断可见性:因为 A 还没提交,所以 B 只能看到 "Tom"

  • T3:事务 A 提交

  • T4:事务 B 再次执行 SELECT

    • 由于在 RR 隔离级别 下,B 使用的还是最初的 Read View

    • 所以仍然看到 "Tom"(保证可重复读)

👉 这就是 MVCC 保证一致性读 的效果。


7. 为什么需要 MVCC?

  • 如果没有 MVCC

    • 所有读操作都必须加锁 → 读写互斥 → 并发性能极差。

  • 有了 MVCC

    • 读操作可以不加锁,直接通过历史版本判断可见性;

    • 读写分离,提升数据库并发性能。


一句话总结:
        MySQL InnoDB 的 MVCC 通过 隐藏字段 + Undo Log + Read View 实现,让事务在并发下能“读旧版本”,从而做到 非阻塞读一致性读,是高性能的关键。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值