redo log的核心作用是保障事务持久性:事务提交后即使MySQL立即宕机,已提交数据也不会丢失;它通过WAL机制先顺序写日志(记录数据页物理修改),崩溃后重放日志恢复脏页,依赖innodb_flush_log_at_trx_commit=1强制刷盘兜底。

redo log 的核心作用就一条:事务提交后哪怕 MySQL 立刻宕机,已提交的数据也不会丢。 它不是锦上添花的优化项,而是 InnoDB 实现事务持久性(Durability)的刚性保障。没有它,MySQL 就无法承诺“commit 成功 = 数据落盘”。
为什么不能直接写磁盘?
InnoDB 所有数据修改都先发生在内存 Buffer Pool 中,形成“脏页”。如果每次 UPDATE 都立刻把整个 16KB 数据页刷到磁盘,会触发大量随机写 —— 机械盘每秒只能扛几百次,SSD 也远不如顺序写快。更致命的是,一个事务可能跨多个不连续的数据页,中途宕机会导致部分页写入、部分未写入,数据库直接损坏。
redo log 把“改了什么”这个动作单独拎出来,用极小体积(只记页号、偏移、新值)、顺序写方式(ib_logfile0、ib_logfile1 循环追加)先落盘。只要这一步成功,崩溃恢复时就能重放日志,把内存里还没来得及刷的脏页“重做”一遍。
innodb_flush_log_at_trx_commit=1 是怎么兜底的?
这个参数决定 redo log 刷盘时机,1 是默认且生产环境唯一安全的选择:
-
0:事务提交时不刷盘,依赖后台线程每秒一次 —— 意外断电或 OS 崩溃,最多丢 1 秒数据; -
1:每次COMMIT都调用fsync()强制刷盘到磁盘 —— 只要磁盘没物理损坏,数据就绝对不丢; -
2:COMMIT时只写入 OS 缓存(write()),不fsync()—— MySQL 进程崩溃不丢,但 OS 崩溃或断电仍可能丢失。
注意:innodb_flush_log_at_trx_commit=1 不等于性能差。现代 SSD + 合理配置(如增大 innodb_log_file_size)下,顺序写吞吐量远高于随机写,实际写入瓶颈往往不在 redo log 本身。
崩溃恢复时 redo log 怎么被读取和重放?
MySQL 启动时,InnoDB 会扫描所有 ib_logfile* 文件,从最后 checkpoint 位置开始读取 redo log 记录,逐条比对当前 Buffer Pool 中页面的 LSN(Log Sequence Number)。若内存中页面的 LSN 小于日志记录中的 LSN,说明该修改尚未刷盘,就执行重做 —— 本质就是把日志里存的“物理修改”再 apply 一遍。
这个过程全自动,无需人工干预。但要注意:如果 redo log 文件损坏或被误删(比如手动 rm ib_logfile*),MySQL 启动会报错 InnoDB: Error: log file ib_logfile0 is missing,且无法启动 —— 因为它失去了恢复依据。
真正容易被忽略的点是:redo log 保护的不只是用户表数据,还包括 undo 页、系统表空间页等所有 Buffer Pool 中的修改。它是一张覆盖全引擎的“安全网”,而不仅仅是“数据页的备份”。


















