InnoDB的MVCC机制是如何实现并发控制的?

InnoDB 的 MVCC(多版本并发控制)机制通过维护数据的多个历史版本,结合事务隔离级别的规则,实现了高效的并发控制。其核心实现依赖于 ​隐藏字段Undo Log ​ 和 ​Read View​ 三大组件,具体工作原理如下:


一、核心组件与作用

  1. 隐藏字段

    每行数据包含三个隐藏字段(非用户定义):

    • DB_TRX_ID​(6字节):记录最后一次修改该行的事务ID。

    • DB_ROLL_PTR​(7字节):回滚指针,指向该行在Undo Log中的历史版本。

    • DB_ROW_ID​(6字节):若表无主键,InnoDB用此字段生成聚簇索引。

      这些字段用于标识数据版本和构建版本链

  2. Undo Log(回滚日志)​

    • 存储数据修改前的旧版本,形成版本链​(通过DB_ROLL_PTR串联)。

    • 分为两类:

      • Insert Undo Log​:事务提交后可直接删除(仅对插入事务可见)。

      • Update Undo Log​:需保留至无事务需要访问旧版本(由Purge线程清理)。

        用于事务回滚和MVCC的快照读

  3. Read View(读视图)​

    事务执行快照读时生成的一致性视图,包含:

    • m_ids:当前活跃(未提交)的事务ID列表。

    • min_trx_id:活跃事务中的最小ID。

    • max_trx_id:下一个待分配的事务ID。

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

      通过比较数据行的DB_TRX_ID与Read View属性,判断版本可见性


二、MVCC工作流程

1. ​读操作(SELECT)​

  • 快照读​(普通SELECT):

    1. 获取当前事务的Read View。

    2. 从数据行的最新版本开始,沿Undo Log版本链回溯。

    3. 根据可见性规则找到第一个符合条件的历史版本:

      • DB_TRX_ID < min_trx_id:版本已提交,可见。
      • DB_TRX_IDm_ids中:版本未提交,不可见。
      • DB_TRX_ID == creator_trx_id:当前事务自身修改,可见。
  • 当前读 ​(如SELECT ... FOR UPDATE):直接读取最新版本并加锁,不依赖MVCC。

2. ​写操作(INSERT/UPDATE/DELETE)​

  • INSERT ​:新记录写入,DB_TRX_ID设为当前事务ID,DB_ROLL_PTR为空。

  • UPDATE/DELETE​:

    1. 将旧数据拷贝到Undo Log,生成新版本。
    2. 更新当前行的DB_TRX_IDDB_ROLL_PTR(指向Undo Log中的旧版本)。
    3. DELETE操作标记删除位,不立即物理删除。

三、隔离级别的实现差异

  1. READ COMMITTED (RC)​

    • 每次SELECT生成新的Read View,能看到其他事务已提交的最新修改。
    • 解决脏读,但可能出现不可重复读。
  2. REPEATABLE READ (RR,InnoDB默认)​

    • 仅在第一次SELECT时生成Read View,后续复用该视图。
    • 保证事务内多次读取数据一致,避免不可重复读。
    • 幻读问题 :MVCC本身无法完全解决,需配合间隙锁(Next-Key Lock)。

四、MVCC的优势与代价

优势 代价
✅ 读写不阻塞(读历史版本,写锁当前版本) ❌ 存储开销(Undo Log保留多版本)
✅ 高并发(减少锁竞争) ❌ 版本链遍历增加CPU开销
✅ 天然支持RC和RR隔离级别 ❌ 长事务阻碍旧版本清理(Purge延迟)

五、总结

InnoDB的MVCC通过版本链快照读机制,实现了非阻塞的并发控制:

  • 读操作 访问历史版本,避免锁竞争;写操作生成新版本,不影响读操作。
  • 隔离级别通过Read View的生成时机(RC每次生成,RR首次生成)实现不同一致性视图。
  • 幻读需结合间隙锁解决,体现MVCC与锁机制的协同设计。

该机制是InnoDB高并发能力的核心,但也需合理管理事务时长和版本清理以避免性能下降。

相关推荐
计算机毕设VX:Fegn08953 小时前
计算机毕业设计|基于springboot + vue医院设备管理系统(源码+数据库+文档)
数据库·vue.js·spring boot·后端·课程设计
Mr__Miss3 小时前
保持redis和数据库一致性(双写一致性)
数据库·redis·spring
Knight_AL4 小时前
Spring 事务传播行为 + 事务失效原因 + 传播行为为什么不用其他模式
数据库·sql·spring
倔强的石头_5 小时前
时序数据时代的“存储与分析困局”解析及金仓解决方案
数据库
计算机毕设VX:Fegn08955 小时前
计算机毕业设计|基于springboot + vue小型房屋租赁系统(源码+数据库+文档)
数据库·vue.js·spring boot·后端·课程设计
倔强的石头_6 小时前
场景化落地指南——金仓时序数据库在关键行业的应用实践
数据库
SelectDB6 小时前
驾驭 CPU 与编译器:Apache Doris 实现极致性能的底层逻辑
运维·数据库·apache
zbguolei6 小时前
MySQL根据身份证号码计算出生日期和年龄
数据库·mysql
马克学长7 小时前
SSM校园图书借阅服务系统jd2z8(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面
数据库·图书管理系统·ssm 框架·ssm 校园图书借阅系统
软件派7 小时前
高斯数据库使用心得——从性能优化到行业实践的深度解析
数据库·oracle