mysql中InnoDB存储引擎的事务回滚与日志恢复

发布时间 - 2026-01-31 00:00:00    点击率:
事务回滚依靠 undo log,而非 redo log;undo log 存于系统表空间或独立 undo 表空间,提交后标记可回收并由 Purge Thread 异步清理,长事务会阻碍 purge 导致空间膨胀。

事务回滚靠的是 undo log,不是 redo log

很多人误以为回滚是用 redo log 做的,其实完全相反:undo log 才是事务回滚的核心依据。InnoDB 在执行 INSERTUPDATEDELETE 时,会先写入对应的 undo log 记录(比如把旧值存下来),这样 ROLLBACK 时就能按链表逆序还原数据。而 redo log 只负责崩溃后重做已提交但未刷盘的修改,跟回滚无关。

关键点:

  • undo log 存在 system tablespace 或独立的 undo tablespace(MySQL 8.0+ 默认启用)中,不是内存结构
  • 事务提交后,undo log 不会立刻删除,而是标记为可回收,由 Purge Thread 异步清理
  • 长事务会阻碍 Purge,导致 undo log 持续增长,甚至撑爆 undo tablespace

崩溃恢复只依赖 redo log,不读 undo log

MySQL 启动时的崩溃恢复流程,只扫描 redo log 文件(如 ib_logfile0),重放其中处于 PREPARE 或已 COMMIT 状态的事务。它根本不会去碰 undo log —— 因为恢复的目标是让数据页状态与最后成功提交的事务一致,而不是“撤销”什么。

实际行为:

  • 如果一个事务只写了 redo log 但没写 commit record(比如掉电发生在 COMMIT 写入一半时),恢复时会被忽略(当作未提交)
  • 如果事务有 CO

    MMIT
    标记,则其所有 redo log 记录都会被重放;即使此时 undo log 还没刷盘,也不影响恢复结果
  • innodb_fast_shutdown=0 会强制做一次完整 purge 和 checkpoint,减少恢复时间;设为 1(默认)则跳过 purge,下次启动时可能多花几秒

如何确认 undo log 是否足够支撑回滚?

没有直接命令能“查看当前 undo log 容量剩余多少”,但可以通过几个关键指标判断是否濒临风险:

SELECT NAME, VALUE FROM performance_schema.global_status 
WHERE NAME IN ('Innodb_undo_tablespaces', 'Innodb_undo_logs', 'Innodb_purge_trx_id');

更实用的是监控活跃事务和历史列表长度:

  • 查长事务:SELECT * FROM information_schema.INNODB_TRX WHERE TIME_TO_SEC(TIMEDIFF(NOW(), TRX_STARTED)) > 60;
  • 看历史列表长度(反映未 purge 的 undo 量):SHOW ENGINE INNODB STATUS\G,搜索 HISTORY LIST 行,超过 10000 就该警惕
  • 检查 undo 表空间大小:SELECT FILE_NAME, FILE_SIZE, MAX_SIZE FROM information_schema.FILES WHERE FILE_TYPE='UNDO LOG';

显式回滚失败的常见原因

ROLLBACK 命令本身极少报错,但“看起来没回滚成功”往往是因为:

  • 事务已经自动提交:例如客户端开启了 autocommit=1,每条语句都是独立事务,ROLLBACK 对它无效
  • 执行了 DDL(如 ALTER TABLE):InnoDB 会在 DDL 前隐式提交当前事务,后续 ROLLBACK 只能回滚 DDL 之后的操作
  • 连接断开或超时:事务可能已被服务端自动回滚,但客户端没收到通知;可通过 SHOW PROCESSLIST 查看 Command 列是否为 SleepTime 超长
  • 使用了 XA START 的分布式事务:必须用 XA ROLLBACK,普通 ROLLBACK 不起作用

真正影响回滚可靠性的,从来不是日志格式或配置参数,而是事务生命周期管理——尤其是别让事务开着不动,也别在事务里调外部 HTTP 接口或等用户输入。这些细节比记住日志类型更容易出问题。


# mysql  # ssl  # red  # 分布式  # select  # 接口  # Thread  # delete  # 异步  # history  # table  # http  # 的是  # 启动时  # 都是  # 客户端  # 重放  # 几个  # 也不  # 是因为  # 还没  # 尤其是 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: 如何自定义建站之星模板颜色并下载新样式?  实例解析angularjs的filter过滤器  浅述节点的创建及常见功能的实现  Laravel安装步骤详细教程_Laravel环境搭建指南  JS弹性运动实现方法分析  Win11怎样安装网易有道词典_Win11安装词典教程【步骤】  米侠浏览器网页背景异常怎么办 米侠显示修复  JavaScript如何实现路由_前端路由原理是什么  学生网站制作软件,一个12岁的学生写小说,应该去什么样的网站?  如何用AI帮你把自己的生活经历写成一个有趣的故事?  如何彻底卸载建站之星软件?  Laravel的契約(Contracts)是什么_深入理解Laravel Contracts与依赖倒置  如何在阿里云购买域名并搭建网站?  Laravel如何部署到服务器_线上部署Laravel项目的完整流程与步骤  Laravel用户认证怎么做_Laravel Breeze脚手架快速实现登录注册功能  使用C语言编写圣诞表白程序  Laravel如何与Vue.js集成_Laravel + Vue前后端分离项目搭建指南  Swift中switch语句区间和元组模式匹配  如何为不同团队 ID 动态生成多个独立按钮  非常酷的网站设计制作软件,酷培ai教育官方网站?  最好的网站制作公司,网购哪个网站口碑最好,推荐几个?谢谢?  深圳防火门网站制作公司,深圳中天明防火门怎么编码?  在线制作视频的网站有哪些,电脑如何制作视频短片?  Laravel怎么调用外部API_Laravel Http Client客户端使用  香港服务器建站指南:免备案优势与SEO优化技巧全解析  Laravel Pest测试框架怎么用_从PHPUnit转向Pest的Laravel测试教程  Laravel如何获取当前登录用户信息_Laravel Auth门面使用与Session用户读取【技巧】  ChatGPT常用指令模板大全 新手快速上手的万能Prompt合集  Android利用动画实现背景逐渐变暗  Win11怎么关闭专注助手 Win11关闭免打扰模式设置【操作】  html5的keygen标签为什么废弃_替代方案说明【解答】  如何用西部建站助手快速创建专业网站?  Python进程池调度策略_任务分发说明【指导】  如何在云主机快速搭建网站站点?  jQuery validate插件功能与用法详解  Laravel怎么连接多个数据库_Laravel多数据库连接配置  高防网站服务器:DDoS防御与BGP线路的AI智能防护方案  JavaScript常见的五种数组去重的方式  Laravel怎么实现一对多关联查询_Laravel Eloquent模型关系定义与预加载【实战】  Laravel如何实现数据库事务?(DB Facade示例)  Laravel Debugbar怎么安装_Laravel调试工具栏配置指南  高端网站建设与定制开发一站式解决方案 中企动力  如何在宝塔面板中创建新站点?  详解免费开源的DotNet二维码操作组件ThoughtWorks.QRCode(.NET组件介绍之四)  阿里云网站搭建费用解析:服务器价格与建站成本优化指南  开心动漫网站制作软件下载,十分开心动画为何停播?  Laravel怎么使用Blade模板引擎_Laravel模板继承与Component组件复用【手册】  文字头像制作网站推荐软件,醒图能自动配文字吗?  网站制作报价单模板图片,小松挖机官方网站报价?  JavaScript 输出显示内容(document.write、alert、innerHTML、console.log)