Redo Log 是 InnoDB 在发生崩溃后保障数据不丢失的核心依据,记录的是页号、偏移量等物理层面的变更信息,而不是 SQL 语句本身。借助 LSN 对齐机制,系统可以高效完成重做恢复,而其数据安全性关键取决于事务提交时日志是否已经真正落盘。

Redo Log 绝不是“可有可无”的组件,它是 InnoDB 崩溃恢复后确保已提交事务不丢失的根本保障——没有它,事务即使提交成功,也可能等同于未发生。
Redo Log 是物理日志,不是 SQL 语句日志
它不会记录 UPDATE user SET name='test' 这样的 SQL 操作,而是保存类似「页号、偏移量、修改前值、修改后值」的物理变更信息。例如:page_id=100, offset=200, old=0x12, new=0x34。这种记录方式的优势在于,MySQL 崩溃恢复时不需要重新解析 SQL,也不必再做复杂的逻辑判断,只需直接将变更应用到对应的数据页,恢复效率非常高。
很多人存在一个常见误区:认为只要开启了 binlog,就不再需要 redo log。实际上,binlog 是 MySQL Server 层的逻辑日志,默认采用异步刷盘;而 redo log 则是 InnoDB 存储引擎层的物理日志,会按顺序写入磁盘文件 ib_logfile0 和 ib_logfile1。两者职责完全不同,既不能互相替代,也分别承担着不同的数据恢复与复制作用。
崩溃恢复依赖 LSN 对齐,不是靠“按时间重放”
每个数据页头部都保存有 page_lsn,表示该页最近一次刷盘时对应的日志位置;而 redo log 文件尾部则维护全局的 log_lsn。MySQL 重启后,InnoDB 只会重做那些 page_lsn < log_lsn 的数据页,也就是尚未真正刷入磁盘的脏页。
- 如果
innodb_flush_log_at_trx_commit = 0,事务提交后日志仅写入内存中的log_buffer,一旦断电就会丢失,最多可能丢失 1 秒数据 - 如果设为
1(默认值),每次事务提交都会调用fsync()将日志落盘,确保 redo log 已持久化到ib_logfile* - 设为
2时,则只是通过fdatasync()写入 OS 缓存,依赖操作系统本身不崩溃,但如果主机突然断电,仍然存在日志丢失风险
Redo Log 文件大小与数量会直接影响恢复速度和写入性能
默认情况下,系统会使用两个文件 ib_logfile0 和 ib_logfile1,共同组成环形缓冲区。其大小由 innodb_log_file_size 控制:如果设置过小,会导致 checkpoint 过于频繁、日志切换次数增加,从而影响写入吞吐;如果设置过大,则在数据库崩溃后需要扫描和重放更多日志,恢复时间也会变长。
因此,调整该参数时必须谨慎:innodb_log_file_size 的修改通常需要停库操作,而且当新旧日志文件大小不一致时,MySQL 启动会拒绝加载。验证方法也很直接:
ls -lh /var/lib/mysql/ib_logfile*
当你看到两个固定大小、权限为 -rw------- 的文件时,通常才说明 redo log 已正常写入并处于有效落盘状态。
还有一个非常容易被忽略的关键点:Redo Log 的数据安全性,不是简单取决于“是否存在”,而是取决于“事务提交的那一刻日志是否已经完成落盘”。即使日志文件配置得再大、数量再多,只要 innodb_flush_log_at_trx_commit 不等于 1,或者磁盘 write cache 未正确关闭(hdparm -W0 /dev/sdX),那么数据库依然可能面临数据丢失风险。
