找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

342

积分

0

好友

46

主题
发表于 昨天 15:48 | 查看: 6| 回复: 0

MVCC (Multiversion Concurrency Control,多版本并发控制) 是 InnoDB 存储引擎为了实现高并发读写而设计的核心机制。它旨在让“写操作不阻塞读操作,读操作也不阻塞写操作”,从而有效提升数据库的并发处理能力。

MVCC 是什么?

简单来说,MVCC 通过维护数据行的多个历史版本,使得读操作(快照读)可以访问到某个一致性快照,而不必读取最新的、可能正在被修改的数据。这主要用于普通的 SELECT 语句(即快照读),例如:

SELECT * FROM user WHERE id = 1;

而对于 SELECT ... FOR UPDATEUPDATEDELETE 等当前读操作,则需要通过加锁来保证数据一致性,不适用 MVCC 机制。

MVCC 的三大核心支柱

MVCC 的实现依赖于三个关键组件:

1. Undo Log(历史版本链)

每当执行 UPDATEDELETE 操作时,InnoDB 不仅会将新数据写入当前行,还会将旧数据拷贝到 Undo Log 中。每行数据都有一个隐藏的 roll_pointer 指针,指向其在 Undo Log 中的上一个版本,从而形成一条从最新版本指向历史版本的单向链表:

最新版本 ← roll_pointer — 上一版本 ← roll_pointer — 更早版本...

这条版本链是 MVCC 能够回溯历史数据的“时光机”。

2. 隐藏字段(trx_id 与 roll_pointer)

InnoDB 为每行数据隐式地添加了两个重要的字段:

  • trx_id:最近一次修改该行数据的事务ID。
  • roll_pointer:指向该行上一个版本数据在 Undo Log 中位置的指针。 这两个字段是 MVCC 实现版本追踪的基础。
3. Read View(可见性规则)

当事务执行快照读时,InnoDB 会为该事务生成一个 Read View(读视图),它是一个快照时刻的系统状态,主要包含:

  • m_ids:生成 Read View 时,系统中活跃(未提交)的事务ID列表。
  • min_trx_idm_ids 中的最小值。
  • max_trx_id:生成 Read View 时,系统已分配的下一个事务ID(即当前最大事务ID+1)。

可见性判断规则:根据当前行的 trx_id 与 Read View 中的信息进行判断,以决定该版本对当前事务是否可见。如果不可见,则通过 roll_pointer 沿 Undo Log 版本链找到上一个版本,并重复此判断过程,直到找到一个可见的数据版本。

MVCC 如何实现“快照读”?

假设一行数据存在版本链:V3(trx_id=30) → V2(trx_id=20) → V1(trx_id=10)。 事务A(trx_id=25)发起快照读,其 Read View 中记录活跃事务可能包含30。

  1. 从最新的 V3 开始判断,发现其 trx_id=30 大于等于 Read View 的 max_trx_id(或存在于m_ids中),对事务A不可见
  2. 通过 roll_pointer 找到上一个版本 V2,其 trx_id=20 小于 Read View 的 min_trx_id,对事务A可见
  3. 因此,事务A读取到的是 V2 版本的数据,而非最新的 V3。这就实现了在事务开始时的一致性读取。

MVCC 在不同隔离级别下的行为差异

MVCC 主要在读已提交(RC)可重复读(RR)这两种隔离级别下发挥作用,但其行为有所不同,这也是理解数据库事务隔离级别的关键。

  • 读已提交 (RC)每次执行快照读时,都会生成一个新的 Read View。因此,每次都能看到最新已提交的数据,这会导致“不可重复读”现象。
  • 可重复读 (RR):在同一个事务内只有第一次执行快照读时会生成一个 Read View,后续所有的快照读都复用这个视图。因此,在整个事务期间,看到的数据快照是一致的,从而避免了不可重复读。

注意:RR 级别下,MVCC 本身无法完全避免幻读。幻读的解决主要依赖于 InnoDB 的 Next-Key Lock(临键锁)机制。MVCC 负责快照读的一致性,而锁负责当前读和写操作的一致性。

MVCC 与锁的关系

这是一个常见的理解难点,两者分工明确: 操作类型 是否加锁 是否使用 MVCC 说明
普通 SELECT 快照读,依赖 MVCC 实现非阻塞读取。
SELECT ... FOR UPDATE 当前读,需要加锁(记录锁、间隙锁等)。
UPDATE / DELETE / INSERT 写操作属于当前读,必须加锁以保证数据正确性。

核心结论:MVCC 是一种乐观并发控制思想在读操作上的体现,它优化了读并发;但对于写操作,InnoDB 仍然使用这种悲观并发控制机制来保证安全。它们是相辅相成的关系。

MVCC 的实用价值与总结

  1. 提升读并发:读操作无需加锁,极大降低了读写事务之间的阻塞,支撑了高并发的 OLTP 场景。
  2. 高效实现事务隔离:为 RC 和 RR 隔离级别提供了高效、无锁的读一致性实现方案。
  3. 一材多用:Undo Log 不仅服务于 MVCC,还用于事务回滚和系统崩溃恢复,设计非常精巧。

总结:InnoDB 的 MVCC 机制,通过 Undo Log 构建数据版本链,利用隐藏字段 trx_idroll_pointer 进行版本追踪,并基于 Read View 的规则来决定数据的可见性。它在不同的隔离级别下通过改变 Read View 的生成策略(RC每次生成,RR首次生成),来平衡“一致性”与“并发度”。理解 MVCC 是深入掌握 MySQL InnoDB 存储引擎并发原理和数据库系统设计思想的基石。




上一篇:Spring观察者模式实战:订单系统解耦与事务一致性避坑指南
下一篇:代码重构实战:5种if/else优化技巧提升可读性
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区(YunPan.Plus) ( 苏ICP备2022046150号-2 )

GMT+8, 2025-12-6 23:56 , Processed in 0.090464 second(s), 38 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2025 CloudStack.

快速回复 返回顶部 返回列表