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

【MySQL数据库】InnoDB实现MVCC(多版本并发控制)底层原理

InnoDB实现MVCC(多版本并发控制)底层原理

  • 一、Undo Log版本链
  • 二、如何通过Undo Log版本链来实现数据库的事务回滚?
      • 一、回滚的触发条件
      • 二、基于Undo Log版本链的回滚核心步骤
        • 步骤1:定位事务的私有Undo Log链表
          • [ 补充 `TRX_ID(事务ID)` 概念 ]
        • 步骤2:按操作类型反向撤销(核心:利用版本链恢复历史数据)
        • 步骤3:释放Undo Log资源(区分“事务回滚”与“事务提交”)
      • 三、关键细节补充:回滚与版本链的联动
      • 总结


一、Undo Log版本链

Undo Log版本链是InnoDB实现MVCC(多版本并发控制)的核心基础之一,本质是一行数据被多次修改后,由各版本的Undo Log记录串联形成的链式结构,用于保存数据的历史版本,支撑事务的一致性读和回滚需求。

其核心逻辑可拆解为3点:

  1. 版本记录来源:当事务修改一行数据时(INSERT/UPDATE/DELETE),InnoDB会先将修改前的旧数据写入Undo Log(如UPDATE时,记录“修改前的字段值、事务ID、指向更早版本的指针”),同时在数据行的隐藏列(如DB_TRX_ID记录修改事务ID、DB_ROLL_PTR记录指向当前版本Undo Log的指针)中关联该Undo Log。
  2. 链式串联逻辑:每次数据被新事务修改,都会生成新的Undo Log条目,新条目中的“前驱指针”会指向之前版本的Undo Log,最终形成一条从“最新数据行”反向指向“最早历史版本”的链表(即版本链)。
  3. 核心作用:事务执行快照读(如普通SELECT)时,会基于ReadView(可见性规则)遍历这条版本链,找到符合“当前事务可见”的历史版本,避免加锁;同时,若事务需要回滚,也可通过版本链恢复到修改前的状态。


二、如何通过Undo Log版本链来实现数据库的事务回滚?

通过Undo Log版本链实现事务回滚,核心逻辑是利用版本链中记录的“数据修改前的历史状态”,反向撤销当前事务对数据的所有修改操作,最终将数据恢复到事务开始前的初始状态。其具体过程可拆解为“回滚触发条件”“核心执行步骤”和“关键细节补充”三部分,如下所示:

一、回滚的触发条件

事务回滚并非主动执行,需满足以下场景之一:

  1. 事务主动发起回滚:开发者显式执行 ROLLBACK 语句(如代码中捕获异常后触发回滚)。
  2. 事务被动回滚:数据库因异常强制终止事务,例如:
    • 事务执行过程中出现错误(如主键冲突、SQL语法错误);
    • 数据库崩溃、断电等硬件/软件故障;
    • 事务超时被数据库强制终止;
    • 并发事务冲突导致的回滚(如乐观锁校验失败)。

二、基于Undo Log版本链的回滚核心步骤

InnoDB会为每个事务维护一个事务私有Undo Log链表(记录该事务所有修改操作对应的Undo Log),回滚时通过遍历这个链表,结合版本链中的历史数据反向恢复,具体步骤如下:

步骤1:定位事务的私有Undo Log链表

每个事务启动时,InnoDB会为其分配唯一的TRX_ID(事务ID),并在事务执行修改操作(INSERT/UPDATE/DELETE)时,将对应的Undo Log条目标记为“归属该TRX_ID”,最终形成一条仅包含当前事务修改记录的Undo Log链表(可理解为“事务的修改操作日志清单”)。

回滚触发时,InnoDB首先根据当前事务的TRX_ID,找到这条专属的Undo Log链表,且遍历顺序是**“从后往前”**(即先撤销最后一次修改,再撤销倒数第二次,直到事务开始前)。


[ 补充 TRX_ID(事务ID) 概念 ]

TRX_ID(事务ID)是InnoDB存储引擎为每个事务分配的唯一标识,是事务并发控制与数据版本管理的核心“身份凭证”,核心作用与特性可简要解析为3点:

  1. 分配规则:事务启动并首次执行修改操作(INSERT/UPDATE/DELETE)时,InnoDB会生成一个自增的TRX_ID分配给该事务(只读事务可能不分配),确保每个事务的标识唯一,避免版本混淆。

  2. 核心用途

    • 标记数据版本归属:数据行的隐藏列DB_TRX_ID会记录“最后修改该行的事务TRX_ID”,用于判断数据版本与当前事务的关联关系;
    • 支撑MVCC可见性判断:事务生成ReadView时,会包含当前活跃事务的TRX_ID列表,结合数据行的DB_TRX_ID,判断该数据版本是否对当前事务可见;
    • 定位事务私有Undo Log:回滚时,InnoDB通过TRX_ID找到该事务专属的Undo Log链表,确保只撤销当前事务的修改操作。
  3. 与事务一致性的关联:TRX_ID的自增特性和唯一标识性,保证了InnoDB能精准追溯数据修改的“发起者”,无论是回滚时定位修改记录,还是MVCC中筛选可见版本,都依赖TRX_ID实现“精准匹配”,最终支撑事务的原子性、隔离性。


步骤2:按操作类型反向撤销(核心:利用版本链恢复历史数据)

不同修改操作(INSERT/UPDATE/DELETE)的回滚逻辑不同,均依赖Undo Log版本链中记录的“历史版本指针”和“旧数据”:

原操作类型Undo Log中记录的关键信息回滚逻辑(反向撤销)
INSERT新插入行的主键、DB_TRX_ID(当前事务ID)直接删除该插入行(因插入行仅当前事务可见,删除后无并发影响)
UPDATE1. 修改前的旧字段值
2. 指向“修改前版本Undo Log”的指针(DB_ROLL_PTR
3. 被修改行的主键
从Undo Log中读取“修改前的旧字段值”,将当前数据行的字段恢复为旧值;同时更新数据行的隐藏列(DB_TRX_ID设为回滚事务ID,DB_ROLL_PTR指向原历史版本的Undo Log),确保版本链完整性
DELETE1. 删除前的完整行数据(含所有字段值)
2. 指向“删除前版本Undo Log”的指针
3. 被删除行的主键
InnoDB的DELETE并非物理删除,而是标记行的“删除位”(DB_FLAG);回滚时只需清除“删除位”,并将Undo Log中记录的“删除前完整数据”写回行中,同时恢复DB_TRX_IDDB_ROLL_PTR,让该行重新可见
步骤3:释放Undo Log资源(区分“事务回滚”与“事务提交”)

回滚完成后,需处理Undo Log的生命周期:

  • 对于INSERT操作的Undo Log:回滚后可直接删除(因插入行已被删除,该Undo Log无后续用途);
  • 对于UPDATE/DELETE操作的Undo Log:需判断是否被其他事务的“快照读”依赖(即其他事务的ReadView是否仍需要该历史版本)。若无人依赖,可标记为“可回收”,后续由InnoDB的Purge线程异步清理;若仍被依赖,则暂时保留,避免影响其他事务的一致性读。

三、关键细节补充:回滚与版本链的联动

  1. 回滚不破坏版本链完整性
    回滚过程中,恢复数据时会同步更新数据行的隐藏列(DB_TRX_IDDB_ROLL_PTR),确保版本链始终是“最新数据→历史版本”的完整链表。例如:事务A修改行X生成版本2,回滚时恢复为版本1,此时行X的DB_ROLL_PTR会重新指向版本1的Undo Log,版本链仍保持“行X(当前)→版本1 Undo Log→更早版本”的结构。

  2. 回滚是“事务级原子操作”
    即使事务包含多个修改操作(如先UPDATE再INSERT),回滚也会“要么全部撤销,要么全部不撤销”——InnoDB通过事务的ACID特性保证回滚的原子性,若回滚过程中出现故障(如断电),重启后会通过事务日志(Redo Log)恢复到回滚前的状态,再重新执行回滚,避免数据不一致。

  3. 与Redo Log的协同
    回滚过程本身也会产生Redo Log(例如:回滚UPDATE时“恢复旧值”的操作,会被记录到Redo Log中)。这是因为若回滚过程中数据库崩溃,重启后可通过Redo Log重演“回滚操作”,确保回滚本身的持久性,避免数据处于“半回滚”状态。

总结

Undo Log版本链为事务回滚提供了“可恢复的历史数据基础”——通过记录每次修改的“旧版本”,回滚时只需反向遍历事务的Undo Log链表,按操作类型恢复数据即可。整个过程既保证了事务的原子性(要么全提交,要么全回滚),又不破坏MVCC依赖的版本链结构,是InnoDB事务一致性的核心支撑。

http://www.dtcms.com/a/409960.html

相关文章:

  • 自己做网站推广关键词网站开发和合同
  • 【Qt开发】输入类控件(二)-> QTextEdit
  • 攻克音频顽疾:基于QCC3095/QCC5181/QCC3040实现全域无冲击声的实战分享
  • 视频融合平台EasyCVR构筑智慧交通可视化管理与智能决策中枢
  • 从特征到应用:用 dlib+OpenCV 实现实时疲劳检测(基于眼睛纵横比)
  • 【买机器人,上BFT】北京大学联合项目 论文解读 | H2R:一种用于机器人视频预训练的人机数据增强技术
  • 音频库管理在数字媒体中的应用探索
  • BLE配网协议 - 分包、组包和重传功能指南
  • MediaHuman YouTube to MP3 多语便携版:高效音频提取工具
  • Java 数组的定义与使用
  • 自建站有哪些站点wordpress前台压缩图片
  • R语言中的获取函数与替换函数
  • 微前端中iframe集成方式与使用微前端框架方式对比
  • 【NOI】在信奥赛中 什么是函数交互题?
  • 电脑上怎么做网站963中华室内设计网
  • Python调用优云智算安装的ComfyUI服务器
  • ACA云原生工程师认证知识点脑图
  • 用 Flink 打造事件驱动流式应用从 DataStream 到 ProcessFunction
  • MySQL学习笔记05:MySQL 索引原理与优化实战指南
  • 【提示工程】Ch2(续)-提示技术(Prompt Technique)
  • 嵌入式软件知识点汇总(day2)
  • QT中QStackedWidget控件功能及应用
  • 网络爬虫(上)
  • 论文精读(六):微服务系统服务依赖发现技术综述
  • 农业推广网站建设企业商城网站建设价格
  • 教师做班级网站手机网站打开微信号
  • 司法审计师:在数字与法律之间行走的“侦探”
  • google drive 怎么断点续传下载?
  • 基于STM32单片机的温湿度臭氧二氧化碳检测OneNET物联网云平台设计
  • LeetCode 面试经典 150_哈希表_快乐数(45_202_C++_简单)(哈希表;快慢指针)