MySQL 8.0 事务撤销日志Undo Log回滚段与 Purge 线程内核微架构在 MySQL InnoDB 存储引擎的内核设计中Undo Log撤销日志承担着两大极其神圣的使命事务回滚Transaction Rollback当事务执行ROLLBACK或发生死锁异常中断时利用 Undo Log 中记录的逆向操作将数据恢复至事务开始前的状态多版本并发控制MVCC 一致性非锁定读当查询发起快照读时通过行记录头部的DB_ROLL_PTR回滚指针沿着 Undo Log 版本链自顶向下遍历构建出符合隔离级别的历史快照版本。然而在生产长跑高并发写入场景下Undo Log 也是引发数据库“亚健康慢性死亡”的最常见元凶之一如果线上存在一个长达数小时未提交的长事务Long-Running TransactionInnoDB 的后台垃圾回收线程Purge Thread就会被彻底卡死导致 Undo 表空间体积呈指数级膨胀数十 GB并在 MVCC 遍历时引发毁灭性的 CPU 100% 满载深入 MySQL 8.0 源码storage/innobase/trx/trx0purge.cc看透回滚段Rollback Segment、History List 链表与 Purge 线程的底层物理微架构。[InnoDB Undo Log 回滚段与 Purge 垃圾回收内核全景] ┌─────────────────────────────────────────────────────────────┐ │ InnoDB 系统全局 128 个 Rollback Segments (回滚段内存槽位) │ │ - 每个回滚段包含 1024 个 Undo Slots (单实例支持 128K 并发事务)│ └──────────────────────────────┬──────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────┐ │ 事务提交 (Commit): │ │ - TRX_UNDO_INSERT: 提交后直接释放, 0 挂入链表 │ │ - TRX_UNDO_MODIFY: 挂入全局 History List (供 MVCC 读快照) │ └──────────────────────────────┬──────────────────────────────┘ │ ▼ (后台 Purge 线程持续异步推进) ┌─────────────────────────────────────────────────────────────┐ │ Purge 线程物理回收微架构 (trx_purge()): │ │ - 抓取全系统当前最老的活跃 ReadView 事务视图 │ │ - 清理所有提交时间戳早于该 ReadView 的历史 Undo 页面 │ │ - 【若存在长事务未提交 ──▶ Purge 被卡死! Undo 空间打爆!】 │ └─────────────────────────────────────────────────────────────┘源码拆解一两种不同的 Undo Log 生命周期在storage/innobase/trx/trx0undo.cc中InnoDB 对事务操作类型做了极其严密的物理区分TRX_UNDO_INSERT插入撤销日志记录新插入记录的物理主键信息极速生命周期由于新插入的记录在未提交前对其他事务完全不可见MVCC 读无需访问它的前序版本事务一旦执行COMMIT该 Undo 页立即被标记为可重用发生 0 挂入 History List 的开销TRX_UNDO_MODIFY更新与删除撤销日志记录被修改字段的旧值镜像MVCC 依赖生命周期事务提交后不能立即物理删除内核将其挂入回滚段的History List链表中供后续并发的一致性快照读Consistent Read沿着DB_ROLL_PTR链表回溯历史版本。源码拆解二Purge 线程的物理回收机制trx_purge()在storage/innobase/trx/trx0purge.cc中Purge 线程在后台不知疲倦地执行异步内存与磁盘空间回收// Purge 线程垃圾回收推进核心源码逻辑 (storage/innobase/trx/trx0purge.cc) ulint trx_purge(ulint n_purge_threads, bool truncate) { // 1. 获取当前系统中最古老的活跃视图 (Oldest Active ReadView) 的低水位快照 trx_id_t purge_up_to_trx_no trx_sys_get_purge_up_to_trx_no(); // 2. 遍历 History List 历史链表 while (undo_page trx_purge_get_next_page(purge_up_to_trx_no)) { // 2.1 物理删除已被标记为 Delete-Mark 的旧记录 (从 B 树叶子节点中物理抹除) row_purge_step(undo_page); // 2.2 释放不再被任何活跃事务依赖的 Undo 物理数据页 trx_undo_mem_free(undo_page); } // 3. 若开启了 undo_log_truncate且文件超过阈值后台执行物理表空间收缩 if (truncate srv_undo_log_truncate) { trx_purge_truncate_history_list(); } }阻塞死穴Purge 线程能够物理清理的最高事务编号严格受限于“全系统中最早开始且尚未提交的那个活跃 ReadView”只要线上存在一个长事务长跑了 3 个小时整整 3 个小时内产生的所有 Undo Log 全部无法被 Purge 线程回收导致History List LengthHLL瞬间飙升至数百万引发系统严重退化[长事务未提交引发的 Undo 堆积与 MVCC 性能雪崩] 事务 T1 (Begin, 未提交长跑 3 小时) ──▶ 【卡住全局 Purge 推进水位!】 高并发更新写入 ──▶ 生成海量 Undo Log ──▶ History List 暴涨至 5,000,000! │ ▼ (严重后果) ┌─────────────────────────────────────────────────────────────┐ │ 1. 任意简单 SELECT 必须沿着 500 万层回滚链深层回溯 (耗时 5s!)│ │ 2. Undo 表空间物理文件膨胀至 100GB 打满磁盘! │ │ 3. CPU 水位瞬间被链表遍历打满至 100%! │ └─────────────────────────────────────────────────────────────┘生产级参数加固与长事务自动熔断为了彻底杜绝 Undo 膨胀隐患我们在 MySQL 8.0 核心主库上实施了严格的内核参数与自动熔断策略-- 1. 开启独立 Undo 表空间与后台全自动物理收缩 (Undo Truncate) SET GLOBAL innodb_undo_tablespaces 4; -- 声明 4 个独立 Undo 表空间 SET GLOBAL innodb_undo_log_truncate ON; -- 开启自动表空间物理收缩 SET GLOBAL innodb_max_undo_log_size 1073741824; -- 单文件超过 1GB 自动触发后台异步重建收缩 SET GLOBAL innodb_purge_threads 4; -- 分配 4 个专用 Purge 并发回收线程 -- 2. 会话级长事务硬防线: 超过 300 秒未提交的长事务自动强制 Kill SET GLOBAL max_execution_time 30000; -- 只读查询 30 秒硬超时总结深入理解 Undo Log 的回滚段槽位管理与 Purge 线程回收边界配置全自动 Truncate 机制才能在持续数天的大促长跑中守住核心数据库 MVCC 一致性读的极致平稳。
企业数字化 ERP 产品动态
相关推荐
店铺介绍范文源码级拆解,搞定性能优化不再迷茫 店铺介绍范文源码级拆解,搞定性能优化不再迷茫 看了一堆教程还是不会写项目?别急,问题不在你,在于没人把“店铺介绍范文”背后的代码逻辑给你扒开看。很多新手盯着文档看,觉得懂了,一上手就卡壳,尤其是涉及数据渲染和 性能优化… · 2026/9/23 9:41:28
Relay 数据驱动应用的基石:useRelayEnvironment Hook 完整指南 前端开发工具 【免费下载链接】relay Relay is a JavaScript framework for building data-driven React applications. 项目地址: https://gitcode.com/gh_mirrors/relay29/relay 点击查看 免费下载 useRelayEnvironment 是 react-relay 提供的核心 Hookÿ… · 2026/9/23 9:41:28
Text2SQL 运营自助取数平台实战:多维异常归因分析生成与自动下钻 Text2SQL 运营自助取数平台实战:多维异常归因分析生成与自动下钻在大促进行到中场阶段时,运营战线人员提出的数据分析诉求,已经从最初简单的“查大盘数字(What happened)”,深度进化为了更为严苛的**“异常… · 2026/9/23 9:41:22
华为悦盒EC6108V9刷机教程:U盘强刷、TTL救砖到当贝桌面,老盒子焕发新生 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/24 13:00:24
服装鞋包行业软件选型指南:从痛点排序到落地实操 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/24 13:00:24
315MHz OOK无线链路工程化实践:从遥控模块到IoT通信子系统 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/24 13:00:24
GDPR十年实效:从合规要求到用户信任工程 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/24 13:00:24
光学基础知识:从透镜成像到景深计算,读懂成像系统设计的关键 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/24 13:00:24
CAN总线DBC文件实战:用CANdb++从零创建整车通信数据库 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/24 13:00:18
基于YOLOv8的渔船作业监控系统:从环境搭建到边缘部署全流程 简介:这是一套面向计算机、人工智能、自动化等专业学生与教师的毕业设计级项目资源,围绕YOLOv8实现渔船作业监控系统,可用于毕设、课程设计、大作业或项目立项演示。压缩包共97个文件,约24.21MB,以70个Python源码文件为… · 2026/9/24 0:00:13
1D-CNN时间序列建模实战:从Conv1d原理到工业落地 简介:面向时间序列数据建模的一维卷积神经网络完整实现,适合深度学习入门者及需要快速验证时序模型的研究者,能够从音频、文本、传感器或股价等序列中挖掘局部特征与时间依赖。压缩包体积很小,只有3KB,内含3个Python脚… · 2026/9/24 0:00:26
柔软的L:汉语语流中被忽视的舌肌张力控制 1. 这个“L”不是字母表里的L,而是舌尖上的L最近在几个方言群和语音教学社群里,反复看到有人发一句:“也说字母L:柔软的长舌”。初看以为是英语发音课笔记,点开才发现全是方言爱好者、播音系学生、语言康复师甚至戏曲演… · 2026/9/24 0:00:44