当前位置: 首页 > news >正文

innodb如何实现mvcc的

InnoDB 实现 MVCC(多版本并发控制)的机制主要依赖于 Undo Log(回滚日志)Read View(读视图)隐藏的事务字段。以下是具体实现步骤和原理:


1. 核心数据结构

InnoDB 的每一行数据(聚簇索引记录)包含两个隐藏字段:

  • DB_TRX_ID:最近修改该行的事务 ID。
  • DB_ROLL_PTR:指向该行旧版本数据的回滚指针(即 Undo Log 的地址)。

2. Undo Log 与版本链

  • Undo Log 的作用
    每次对数据进行修改(INSERT/UPDATE/DELETE),InnoDB 会生成 Undo Log,记录修改前的数据镜像。
  • 版本链的构建
    通过 DB_ROLL_PTR 字段,将同一行数据的多个版本按修改顺序链接成链表。
    示例
    当前行 → [版本3: trx_id=300, roll_ptr → 版本2]  
                ↑  
    版本2 → [trx_id=200, roll_ptr → 版本1]  
                ↑  
    版本1 → [trx_id=100, roll_ptr → NULL]
    

3. Read View 的生成

当事务执行 一致性读(如 SELECT)时,InnoDB 为其生成一个 Read View,包含以下信息:

  • m_ids:当前活跃(未提交)的事务 ID 列表。
  • min_trx_idm_ids 中的最小事务 ID。
  • max_trx_id:下一个即将分配的事务 ID(即当前最大事务 ID +1)。
  • creator_trx_id:创建该 Read View 的事务 ID(仅当该事务自身有修改时存在)。

4. 数据可见性判断规则

对于某一数据行的版本,判断其对当前事务是否可见的规则如下:

  1. 版本的事务 ID < min_trx_id
    该版本已提交,可见。
  2. 版本的事务 ID ≥ max_trx_id
    该版本由未来事务生成,不可见。
  3. min_trx_id ≤ 版本的事务 ID < max_trx_id
    • 若版本的事务 ID 不在 m_ids,说明该事务已提交,可见。
    • 若版本的事务 ID m_ids,说明该事务未提交,不可见。
  4. 版本的事务 ID = creator_trx_id
    该版本由当前事务自身修改,可见。

5. MVCC 的查询流程

  1. 定位最新数据行:通过聚簇索引找到当前行的最新版本。
  2. 遍历版本链:从最新版本开始,根据 DB_ROLL_PTR 回溯旧版本。
  3. 可见性检查:对每个版本应用 Read View 规则,找到第一个可见的版本。

示例
假设事务 A(trx_id=200)的 Read View 中:

  • m_ids = [100, 300]
  • min_trx_id=100, max_trx_id=400

遍历某行的版本链:

  • 版本3(trx_id=300):在 m_ids 中 → 不可见。
  • 版本2(trx_id=200):等于 creator_trx_id → 可见(若事务 A 修改了该行)。
  • 版本1(trx_id=100):在 m_ids 中 → 不可见。
  • 版本0(trx_id=50):小于 min_trx_id → 可见。

最终事务 A 读取到版本0。


6. 不同隔离级别的实现差异

  • 读已提交(Read Committed)
    每次执行 SELECT 时生成新的 Read View,看到已提交的最新数据。
  • 可重复读(Repeatable Read)
    事务内第一次 SELECT 时生成 Read View,后续复用该视图,保证多次读取一致性。

7. Undo Log 的清理

  • Insert Undo Log:事务提交后立即删除(不参与 MVCC)。
  • Update/Delete Undo Log:需保留至所有可能访问旧版本的事务结束(通过 purge 线程异步清理)。

8. MVCC 与锁的协同

  • 写操作(UPDATE/DELETE)
    即使使用 MVCC,写操作仍需加锁(如行锁)避免脏写。
  • 读操作(SELECT)
    默认无锁,通过 MVCC 读取快照版本。若需锁定读,可加锁(如 SELECT ... FOR UPDATE)。

总结

InnoDB 通过以下机制实现 MVCC:

  1. 版本链:通过 DB_ROLL_PTR 链接数据的历史版本。
  2. Read View:判断事务可见性的依据。
  3. Undo Log:存储历史版本数据,支持版本链回溯。
  4. 隔离级别适配:通过动态生成或复用 Read View 实现不同隔离级别。
# MVCC 执行示例
事务A(trx_id=200)读取某行数据:
1. 找到最新版本(trx_id=300)。
2. 检查 Read View:m_ids=[100, 300], min=100, max=400。
3. trx_id=300 在 m_ids 中 → 不可见。
4. 回溯到版本2(trx_id=200),等于 creator_trx_id → 可见。

相关文章:

  • 【JS】使用滑动窗口得到无重复字符的最长子串
  • Linux系统高级IO
  • 还是主题混合程序设计
  • Redash:一个开源的数据查询与可视化工具
  • 如何查看 MySQL 的磁盘空间使用情况:从表级到数据库级的分析
  • YOLOv12 训练从这里开始:LabelImg 标注数据集
  • 详解 MySQL 索引的最左前缀匹配原则
  • 【C语言】内存函数
  • SQLark(百灵连接):一款面向信创应用开发者的数据库开发和管理工具
  • 一周学会Pandas2 Python数据处理与分析-NumPy数组创建
  • 网络建设与运维神州数码DCN 基于流的重定向
  • LVGL修改标签文本,GUI Guider的ui不生效
  • 实验研究:不同物体与落点材质对弹起高度的影响
  • app逆向专题一:如何下载app
  • 【C++】多线程编程大礼包
  • Java 责任链模式 详解
  • 初阶数据结构--树
  • 第五章、 虚拟内存
  • PowerPhotos:拯救你的Mac照片库,告别苹果原生应用的局限
  • 2140. 解决智力问题