redo log 是 innodb 存储引擎的物理日志,用于保证已提交事务不丢失;它记录数据页的物理修改位置与内容,顺序写入、体积小、性能高;通过 innodb_flush_log_at_trx_commit 控制落盘时机,推荐 oltp 使用 1;调优需结合写入压力,避免过小导致频繁 checkpoint 或过大延长恢复时间。

Redo Log 是什么:先写日志再改数据的“保险单”
Redo Log 不是 MySQL Server 层的日志,而是 InnoDB 存储引擎自己维护的一套物理日志,它的核心作用就一个:保证已提交事务不丢。哪怕服务器突然断电、崩溃,只要 redo log file 里有记录,重启后就能把那些“只写进内存、还没刷到表空间”的修改重做一遍。
它不是记录 SQL(像 binlog 那样),也不是记录旧值(像 undo log 那样),而是记录“某个表空间 ID 的第 X 页、偏移量 Y 处,写了 Z 字节的新数据”。这种格式极小、写入极快,且全部是顺序追加——这才是它能扛住高并发写入的关键。
为什么不能直接写磁盘:随机 IO 和页粒度的代价
InnoDB 修改数据时,先在 Buffer Pool 中改内存页;如果每次提交都把整个 16KB 的页刷盘,会面临两个硬伤:
- 浪费:可能只改了 1 个字节,却要写满 16KB
- 慢:一个事务涉及多个非连续页,刷盘就是大量随机 IO,磁盘扛不住
而 redo log 只记“改了哪、改多少、改成啥”,几字节到几十字节不等,写入 ib_logfile0、ib_logfile1 这类固定大小的循环文件,全程顺序 IO —— 性能差距是数量级的。
怎么控制 redo log 落盘时机:innodb_flush_log_at_trx_commit 的三种取值
这个参数直接决定事务提交时日志是否真正落盘,是性能和安全的分水岭:
-
1(默认):每次COMMIT都调用fsync()刷盘 → 最安全,但吞吐受限 -
0:每秒由后台线程统一刷一次redo log buffer→ 性能最好,但崩溃最多丢 1 秒事务 -
2:每次COMMIT写入 OS page cache,不fsync→ 折中,OS 崩溃才丢,MySQL 崩溃不丢
线上 OLTP 系统建议保持 1;压测或日志型中间件可临时调成 2,但别碰 0 —— 它连内核 panic 都救不了。
查看和调优 redo log:别只看大小,要看循环写压力
关键配置项只有两个:innodb_log_file_size 和 innodb_log_files_in_group。前者单个日志文件大小(如 256M),后者文件个数(默认 2),两者相乘就是总日志空间。
调得太小会导致频繁 checkpoint,拖慢写入;太大又延长崩溃恢复时间。实操建议:
- 观察
SHOW ENGINE INNODB STATUS中的Log sequence number和Last checkpoint at差值,持续接近总日志容量(比如差值常在 90% 以上),说明日志太小 - 调整前必须停库,且需删除旧
ib_logfile*文件并重启 —— 这步漏掉会导致启动失败 - 8.0+ 版本支持在线调整
innodb_log_file_size,但仅限增大,且仍需满足总容量 ≥ 当前 LSN 增长速率 × 1 小时
真正容易被忽略的是:redo log 不是越大越好,而是要匹配你的写入峰值节奏。一次大事务批量更新千万行,和持续每秒几百条小更新,对日志空间的压力模型完全不同。











