浅析MySQL事务中的redo与undo
我们都知道事务有4种特性原子性、一致性、隔离性和持久性在事务中的操作要么全部执行要么全部不做这就是事务的目的。事务的隔离性由锁机制实现原子性、一致性和持久性由事务的redo 日志和undo 日志来保证。所以本篇文章将讨论关于事务中的redo和undo的几个问题redo 日志与undo日志分别是什么redo 如何保证事务的持久性undo log 是否是redo log的逆过程redo logRedo 的类型重做日志(redo log)用来保证事务的持久性即事务ACID中的D。实际上它可以分为以下两种类型物理Redo日志逻辑Redo日志在InnoDB存储引擎中大部分情况下 Redo是物理日志记录的是数据页的物理变化。而逻辑Redo日志不是记录页面的实际修改而是记录修改页面的一类操作比如新建数据页时需要记录逻辑日志。关于逻辑Redo日志涉及更加底层的内容这里我们只需要记住绝大数情况下Redo是物理日志即可DML对页的修改操作均需要记录Redo.Redo 的作用Redo log的主要作用是用于数据库的崩溃恢复Redo 的组成Redo log可以简单分为以下两个部分一是内存中重做日志缓冲 (redo log buffer),是易失的在内存中二是重做日志文件 (redo log file)是持久的保存在磁盘中什么时候写Redo?上面那张图简单地体现了Redo的写入流程这里再细说下写入Redo的时机在数据页修改完成之后在脏页刷出磁盘之前写入redo日志。注意的是先修改数据后写日志redo日志比数据页先写回磁盘聚集索引、二级索引、undo页面的修改均需要记录Redo日志。Redo的整体流程下面以一个更新事务为例宏观上把握redo log 流转过程如下图所示第一步先将原始数据从磁盘中读入内存中来修改数据的内存拷贝第二步生成一条重做日志并写入redo log buffer记录的是数据被修改后的值第三步当事务commit时将redo log buffer中的内容刷新到 redo log file对 redo log file采用追加写的方式第四步定期将内存中修改的数据刷新到磁盘中redo如何保证 事务的持久性InnoDB是事务的存储引擎其通过Force Log at Commit 机制实现事务的持久性即当事务提交时先将 redo log buffer 写入到 redo log file 进行持久化待事务的commit操作完成时才算完成。这种做法也被称为Write-Ahead Log(预先日志持久化)在持久化一个数据页之前先将内存中相应的日志页持久化。为了保证每次日志都写入redo log file在每次将redo buffer写入redo log file之后默认情况下InnoDB存储引擎都需要调用一次fsync操作,因为重做日志打开并没有 O_DIRECT选项所以重做日志先写入到文件系统缓存。为了确保重做日志写入到磁盘必须进行一次 fsync操作。fsync是一种系统调用操作其fsync的效率取决于磁盘的性能因此磁盘的性能也影响了事务提交的性能也就是数据库的性能。(O_DIRECT选项是在Linux系统中的选项使用该选项后对文件进行直接IO操作不经过文件系统缓存直接写入磁盘)上面提到的Force Log at Commit机制就是靠InnoDB存储引擎提供的参数innodb_flush_log_at_trx_commit来控制的该参数可以控制 redo log刷新到磁盘的策略设置该参数值也可以允许用户设置非持久性的情况发生具体如下当设置参数为1时默认为1表示事务提交时必须调用一次fsync操作最安全的配置保障持久性当设置参数为2时则在事务提交时只做write操作只保证将redo log buffer写到系统的页面缓存中不进行fsync操作因此如果MySQL数据库宕机时 不会丢失事务但操作系统宕机则可能丢失事务当设置参数为0时表示事务提交时不进行写入redo log操作这个操作仅在master thread 中完成而在master thread中每1秒进行一次重做日志的fsync操作因此实例 crash 最多丢失1秒钟内的事务。master thread是负责将缓冲池中的数据异步刷新到磁盘保证数据的一致性fsync和write操作实际上是系统调用函数在很多持久化场景都有使用到比如 Redis 的AOF持久化中也使用到两个函数。fsync操作 将数据提交到硬盘中强制硬盘同步将一直阻塞到写入硬盘完成后返回大量进行fsync操作就有性能瓶颈而write操作将数据写到系统的页面缓存后立即返回后面依靠系统的调度机制将缓存数据刷到磁盘中去,其顺序是user buffer—— page cache——disk。除了上面谈到的Force Log at Commit机制保证事务的持久性实际上重做日志的实现还要依赖于mini-transaction。Redo在InnoDB中是如何实现的与mini-transaction的联系Redo的实现实则跟mini-transaction紧密相关mini-transaction是一种InnoDB内部使用的机制通过mini-transaction来保证并发事务操作下以及数据库异常时数据页中数据的一致性但它不属于事务。为了使得mini-transaction保证数据页数据的一致性mini-transaction必须遵循以下三种协议The FIX RulesWrite-Ahead LogForce-log-at-commitThe FIX Rules修改一个数据页时需要获得该页的x-latch(排他锁)获取一个数据页时需要该页的s-latch(读锁或者称为共享锁) 或者是 x-latch持有该页的锁直到修改或访问该页的操作完成。Write-Ahead Log在前面阐述中就提到了Write-Ahead Log(预先写日志)。在持久化一个数据页之前必须先将内存中相应的日志页持久化。每个页都有一个LSN(log sequence number)代表日志序列号LSN占用8字节单调递增), 当一个数据页需要写入到持久化设备之前要求内存中小于该页LSN的日志先写入持久化设备那为什么必须要先写日志呢可不可以不写日志直接将数据写入磁盘原则上是可以的只不过会产生一些问题数据修改会产生随机IO但日志是顺序IOappend方式顺序写是一种串行的方式这样才能充分利用磁盘的性能。Force-log-at-commit这一点也就是前文提到的如何保证事务的持久性的内容这里再次总结一下与上面的内容相呼应。在一个事务中可以修改多个页Write-Ahead Log 可以保证单个数据页的一致性但是无法保证事务的持久性Force-log-at-commit 要求当一个事务提交时其产生所有的mini-transaction 日志必须刷新到磁盘中若日志刷新完成后在缓冲池中的页刷新到持久化存储设备前数据库发生了宕机那么数据库重启时可以通过日志来保证数据的完整性。重做日志的写入流程上图表示了重做日志的写入流程每个mini-transaction对应每一条DML操作比如一条update语句其由一个mini-transaction来保证对数据修改后产生redo1首先将其写入mini-transaction私有的Buffer中update语句结束后将redo1从私有Buffer拷贝到公有的Log Buffer中。当整个外部事务提交时将redo log buffer再刷入到redo log file中。undo logundo log的定义undo log主要记录的是数据的逻辑变化为了在发生错误时回滚之前的操作需要将之前的操作都记录下来然后在发生错误时才可以回滚。undo log的作用undo是一种逻辑日志有两个作用用于事务的回滚MVCC关于MVCC(多版本并发控制)的内容这里就不多说了本文重点关注undo log用于事务的回滚。undo日志只将数据库逻辑地恢复到原来的样子在回滚的时候它实际上是做的相反的工作比如一条INSERT 对应一条 DELETE对于每个UPDATE,对应一条相反的 UPDATE,将修改前的行放回去。undo日志用于事务的回滚操作进而保障了事务的原子性。undo log的写入时机DML操作修改聚簇索引前记录undo日志二级索引记录的修改不记录undo日志需要注意的是undo页面的修改同样需要记录redo日志。undo的存储位置在InnoDB存储引擎中undo存储在回滚段(Rollback Segment)中,每个回滚段记录了1024个undo log segment而在每个undo log segment段中进行undo 页的申请在5.6以前Rollback Segment是在共享表空间里的5.6.3之后可通过 innodb_undo_tablespace设置undo存储的位置。undo的类型在InnoDB存储引擎中undo log分为insert undo logupdate undo loginsert undo log是指在insert 操作中产生的undo log因为insert操作的记录只对事务本身可见对其他事务不可见。故该undo log可以在事务提交后直接删除不需要进行purge操作。而update undo log记录的是对delete 和update操作产生的undo log该undo log可能需要提供MVCC机制因此不能再事务提交时就进行删除。提交时放入undo log链表等待purge线程进行最后的删除。补充purge线程两个主要作用是清理undo页和清除page里面带有Delete_Bit标识的数据行。在InnoDB中事务中的Delete操作实际上并不是真正的删除掉数据行而是一种Delete Mark操作在记录上标识Delete_Bit而不删除记录。是一种假删除,只是做了个标记真正的删除工作需要后台purge线程去完成。undo log 是否是redo log的逆过程undo log 是否是redo log的逆过程其实从前文就可以得出答案了undo log是逻辑日志对事务回滚时只是将数据库逻辑地恢复到原来的样子而redo log是物理日志记录的是数据页的物理变化显然undo log不是redo log的逆过程。redo undo总结下面是redo log undo log的简化过程便于理解两种日志的过程假设有A、B两个数据值分别为1,2. 1. 事务开始 2. 记录A1到undo log 3. 修改A3 4. 记录A3到 redo log 5. 记录B2到 undo log 6. 修改B4 7. 记录B4到redo log 8. 将redo log写入磁盘 9. 事务提交实际上在insert/update/delete操作中redo和undo分别记录的内容都不一样量也不一样。在InnoDB内存中一般的顺序如下写undo的redo写undo修改数据页写Redo小结本文分析了事务中的redo和undo日志参考了一些资料书籍整理得出可能有些地方表述的不清楚。如有不对之处欢迎指出。参考资料 鸣谢MySQL技术内幕InnoDB存储引擎第2版MySQL内核InnoDB存储引擎 卷1InnoDB 日志/回滚段/崩溃恢复实现详解MySQL · 引擎特性 · InnoDB redo log漫游MySQL的undo,redo,二阶段提交思维导图作者pjmike链接https://www.jianshu.com/p/20e10ed721d0来源简书著作权归作者所有。商业转载请联系作者获得授权非商业转载请注明出处。## 一、数据页Page ### 1.1 定义 - InnoDB 磁盘和内存之间读写的最小单位默认 **16KB**。 - 不是按行读写而是**按页读写**。查一行也会加载整个 16KB 页到 Buffer Pool。 ### 1.2 页内结构 - 文件头File Header - 页头Page Header - 用户记录行数据 - 空闲空间 - 页目录Page Directory - 文件尾File Trailer ### 1.3 查找与连接 - 页内记录用单向链表按主键串联页目录用槽位做二分查找。 - 页间双向链表B 树叶子节点就是数据页非叶子节点存索引键 页号。 ### 1.4 为什么是 16KB - 磁盘 IO、内存占用、树高度之间的折中。 - 三层 B 树约能存 2000 万行。 - 页太小 → 树变高、IO 次数多页太大 → 单次 IO 浪费、内存碎片。 ### 1.5 页类型 - 数据页INDEX - Undo 页 - 系统页 - 事务数据页 ⚠️ 坑平时说的数据页通常指 B 树的索引页但页还有 Undo 页、系统页、事务数据页等类型。 --- ## 二、三大日志职责对照 | 日志 | 归属层 | 存什么 | 作用 | |---|---|---|---| | **undo log** | InnoDB 引擎层 | 旧值 / 反向操作逻辑 | 事务回滚 MVCC 历史版本 | | **redo log** | InnoDB 引擎层 | 页的变更物理/逻辑 | 崩溃恢复、持久性 | | **binlog** | MySQL Server 层 | 逻辑变更事件SQL 或行变化 | 主从复制 时间点恢复 | ### 2.1 undo log 细节 - 作用一事务回滚记录数据修改前的旧值回滚时反向操作。 - 作用二MVCC 多版本读读已提交/可重复读下其他事务读到的是 undo 里的历史版本。 - 不负责把数据持久化到磁盘负责回到过去。 ### 2.2 redo log 细节 - 作用崩溃恢复。事务提交时先写 redo log顺序写、快再慢慢刷脏页到磁盘随机写、慢即 WALWrite-Ahead Logging。 - 宕机重启后用 redo log 重放已提交但未刷盘的数据。 ### 2.3 binlog 细节 - 记录逻辑变更事件用于主从复制和基于时间点的恢复。 - 归属 MySQL Server 层与存储引擎无关。 ⚠️ 坑 1**redo log 存的不是回滚 SQL**回滚 SQL 是 undo log 的事。 ⚠️ 坑 2**binlog 不是从 redo log buffer 写出来的**两者是完全独立的两套日志。 --- ## 三、redo log vs binlog 写入路径重点防坑 ### 3.1 两条并行链路数据不互相流转数据修改 ──┬── redo log buffer ── redo log fileib_logfile循环写└── binlog cache ── binlog filebinlog.000001…追加写text### 3.2 对比表 | | redo log | binlog | |---|---|---| | 归属层 | InnoDB 引擎层 | MySQL Server 层 | | 内存缓冲 | redo log buffer全局一份 | binlog cache每线程一份 | | 落盘文件 | redo log file | binlog file | | 写入方式 | 循环写空间固定 | 追加写不断切新文件 | ⚠️ 坑 3redo log buffer 只服务 redo log file**不会变成 binlog**。 --- ## 四、事务提交两阶段提交2PC ### 4.1 提交顺序修改数据 → 写 redo log buffer状态标记 prepare写 binlog → binlog cache → 刷到 binlog file提交事务 → redo log 状态改为 committext### 4.2 崩溃恢复判断 判断依据**binlog 是否完整写完。** | 崩溃场景 | 恢复动作 | |---|---| | redo 已 preparebinlog 未写完整 | **回滚**该事务 | | redo 已 preparebinlog 已写完整 | **提交**该事务 | ### 4.3 目的 - 让 redo log 和 binlog 逻辑一致要么都生效要么都不生效。 - 否则主从/恢复会出问题。 --- ## 五、binlog 三种格式 ### 5.1 STATEMENT语句级 - 记录原始 SQL 语句本身 sql UPDATE users SET name B WHERE id 1;优点日志小。缺点NOW()、RAND()、LIMIT 不带 ORDER BY 等在主从库执行结果可能不一致。5.2 ROW行级MySQL 5.7 默认记录每一行被改成什么样不记 SQL。优点主从一致性强不依赖 SQL 语义。缺点一条批量 UPDATE 可能产生海量 binlog日志大。5.3 MIXEDMySQL 自动在 STATEMENT 和 ROW 之间切换。一般用 STATEMENT遇到不安全的语句改用 ROW。5.4 对比表格式记录内容优点缺点STATEMENT原始 SQL 语句日志小部分函数/语句可能主从不一致ROW5.7 默认每行改成什么样主从一致性强批量 UPDATE 日志可能巨大MIXED自动在两者间切换折中行为依赖语句类型六、一条 UPDATE 三个 log 各写什么执行sqlUPDATE users SET name B WHERE id 1; -- 原值 name A日志记录内容undo logid1 的 name 原值是 A回滚时改回 Aredo log某数据页某偏移处值从 A 改成 B用于重放binlogROW 格式id1 这行 name 从 A 变 B 的行事件STATEMENT 格式那条 UPDATE SQL七、一句话总结undo log记旧值 → 回滚 MVCCredo log记页变更 → 崩溃恢复持久性binlog记逻辑变更 → 主从复制 归档恢复三种 log 各司其职互不替代redo 管崩溃恢复undo 管回滚和 MVCCbinlog 管主从复制和归档。

相关新闻

puzzle(0335)色块拼图、物换星移、移星掠形

puzzle(0335)色块拼图、物换星移、移星掠形

目录 一,纯色块拼图——旋转 二,物换星移 三,三角形纯色块拼图——旋转 2*2*2模式 3*3*3模式 四,六边形纯色块拼图——旋转 2*2*2模式 3*3*3模式 五,纯色块拼图——轮换 六,移星掠形 练习模式 …

2026/9/27 19:54:00 阅读更多 →
Python | URL长链接转短链接

Python | URL长链接转短链接

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/27 2:17:11 阅读更多 →
Fiddler 通用数据抓包从环境配置到接口分析与数据保存

Fiddler 通用数据抓包从环境配置到接口分析与数据保存

在网页开发、接口调试和数据分析过程中,经常需要弄清楚一个问题:页面上的数据究竟是从哪里来的? 例如,点击“下一页”时,浏览器向服务器发送了什么参数?提交表单后,服务器返回了哪些内容?页面显示“加载失败”,究竟是请求没有发出去,还是接口返回了错误? Fiddler …

2026/9/26 18:27:07 阅读更多 →

最新新闻

JSAR 开发环境配置与项目初始化全流程指南:VS Code + Node.js 接入 TaoToken 统一 Key

JSAR 开发环境配置与项目初始化全流程指南:VS Code + Node.js 接入 TaoToken 统一 Key

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/28 3:58:05 阅读更多 →
OpenClaw 任务编排实战:用 Skill 与 Plugin 把简单指令升级为复杂工作流

OpenClaw 任务编排实战:用 Skill 与 Plugin 把简单指令升级为复杂工作流

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/28 3:58:05 阅读更多 →
当下效果出众的SEO优化服务机构都有哪些?

当下效果出众的SEO优化服务机构都有哪些?

痛点深度剖析我们团队在实践中发现,当下SEO优化领域存在诸多困境。一方面在流量获取上,SEO见效缓慢,部分客户做了半年优化,关键词排名毫无起色,而SEM成本却持续攀升,谷歌广告点击成本高,ROI难以…

2026/9/28 3:58:05 阅读更多 →
深圳企业网站建设制作公司实战:从零搭建被忽略的SEO底层逻辑

深圳企业网站建设制作公司实战:从零搭建被忽略的SEO底层逻辑

深圳企业网站建设制作公司实战:从零搭建被忽略的SEO底层逻辑 网站做好了没人访问,这才是最让人头秃的痛点。很多深圳老板找我们做网站,交钱时很爽快,上线后流量却像死水一样。问题往往不在设计多丑,而在底层架构就没打好地基。今天不讲虚的,直接拆解…

2026/9/28 3:58:05 阅读更多 →
VC++ Ogre网络RPG骨架:TCP协议+多渲染器+服务端权威同步

VC++ Ogre网络RPG骨架:TCP协议+多渲染器+服务端权威同步

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/28 3:58:04 阅读更多 →
使用 type-graphql 与 Prisma 集成:基于 Prisma Schema 自动生成类型类与 CRUD Resolver 的实战指南

使用 type-graphql 与 Prisma 集成:基于 Prisma Schema 自动生成类型类与 CRUD Resolver 的实战指南

后端GraphQLAPI设计 【免费下载链接】type-graphql Create GraphQL schema and resolvers with TypeScript, using classes and decorators! 项目地址: https://gitcode.com/gh_mirrors/ty/type-graphql 点击查看 免费下载 导读 本文聚焦 type-graphql 项目中与 P…

2026/9/28 3:57:04 阅读更多 →

日新闻

济南做网站多少钱:3个案例拆解,防黑源码下载全攻略

济南做网站多少钱:3个案例拆解,防黑源码下载全攻略

济南做网站多少钱:3个案例拆解,防黑源码下载全攻略 上周济南一个做建材的老板找我,脸都绿了。他的官网首页弹出了赌博广告,后台被植入了挖矿脚本。他慌得问我:“网站被黑挂马不知道怎么办?能不能直接找之前的外包公司要源码下载,看看哪里被动了手脚?…

2026/9/28 0:00:34 阅读更多 →
婚恋网站实战案例:避开3个高价坑,省钱50%还能跑赢流量

婚恋网站实战案例:避开3个高价坑,省钱50%还能跑赢流量

婚恋网站实战案例:避开3个高价坑,省钱50%还能跑赢流量 找婚恋网站建站公司,最怕的就是被坑高价。很多同行跟我吐槽,报价单上写得模棱两可,功能栏里全是“高级定制”、“专属UI”,结果落地全是套壳。今天不聊虚的,直接甩几个我经手的 实战案例…

2026/9/28 0:00:34 阅读更多 →
制作网页比较方便的软件怎么选?一文搞懂避坑指南

制作网页比较方便的软件怎么选?一文搞懂避坑指南

制作网页比较方便的软件怎么选?一文搞懂避坑指南 很多老板一上来就问:做个网站多少钱?但我反问他:你的域名买了吗?服务器租了吗?他一脸懵。这就是典型的“域名服务器搞不懂”。别急,今天咱们不聊虚的,直接 一文搞懂 那些让你头秃的技术名词。…

2026/9/28 0:00:34 阅读更多 →

周新闻

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解 【免费下载链接】spirula-studio Cross-vendor 3D Gaussian Splatting trainer - video to splat to mesh, Vulkan or CUDA. 项目地址: https://gitcode.com/GitHub_Trending/sp/spirula-studio Sp…

2026/9/27 0:00:34 阅读更多 →
SEO怎么推广速查手册新手避坑实战指南

SEO怎么推广速查手册新手避坑实战指南

SEO怎么推广速查手册新手避坑实战指南 模板网站太丑不够用?别急着加滤镜,那是治标不治本。很多老板盯着后台流量掉得眼红,却还在纠结首页Banner的圆角是不是3像素。这就像穿着西装去挖土,姿势不对,努力白费。我整理这份 速查手册…

2026/9/27 0:00:34 阅读更多 →
FireRed-OpenStoryline少样本仿写深度解析:AI Agent如何复刻你的独特文案风格与节奏

FireRed-OpenStoryline少样本仿写深度解析:AI Agent如何复刻你的独特文案风格与节奏

FireRed-OpenStoryline少样本仿写深度解析:AI Agent如何复刻你的独特文案风格与节奏 【免费下载链接】FireRed-OpenStoryline FireRed-OpenStoryline is an AI video editing agent that transforms manual editing into intention-driven directing through natural language …

2026/9/27 0:00:34 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

2026/9/27 9:12:14 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

2026/9/28 3:51:11 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步分类:[工程技术]细分主题:Docker 容器化技术与镜像安全管理:核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用(包含 Web 接口、后台…

2026/9/26 22:52:30 阅读更多 →