mysql redo log是什么_mysql崩溃恢复机制

7次阅读

MySQL 崩溃后能恢复已提交数据,靠的是 InnoDB 的 redo log 物理日志,它记录页级修改并支持前滚恢复;其生效标志是启动日志中出现“Doing recovery”提示,关键配置为 innodb_flush_log_at_trx_commit 和 innodb_log_file_size。

mysql redo log 是什么_mysql 崩溃恢复机制

MySQL 崩溃后能恢复数据,靠的就是 redo log —— 它不是备份,也不是 binlog,而是 InnoDB 引擎写在磁盘上的“操作快照”,专为崩溃恢复而生。

为什么 MySQL 崩溃后不丢已提交的数据?

因为事务提交前,InnoDB 已经把这次修改的物理操作(比如“页号 123 的偏移量 456 处写入值 0xABC”)记到了 redo log 文件里,并按配置刷了盘。崩溃重启时,InnoDB 会自动扫描 ib_logfile*,重放所有已提交但还没写进数据文件(.ibd)的变更。

  • 这个过程叫 recovery(前滚恢复),只重做,不回滚
  • 它不依赖 binlog;即使 log_bin 关着,redo log 照样工作
  • 恢复粒度是 page(16KB),不是行或 SQL,所以它是物理日志

怎么确认 redo log 正在起作用?

看 MySQL 启动日志里有没有类似 InnoDB: Doing recovery: scanned up to log sequence number XXX 这样的输出。这是最直接的证据——说明 InnoDB 正在读 redo log 并重放。

  • 启动时若发现 ib_logfile0ib_logfile1 存在且非空,InnoDB 就一定会执行 recovery
  • 可通过 SHOW ENGINE INNODB STATUSG 查看 LOG 小节,关注 Log sequence numberLog flushed up to 是否接近
  • 手动模拟崩溃:用 kill -9 杀掉 mysqld 进程,再启动,观察 error log —— 不会报数据不一致,就是 redo log 在兜底

哪些配置直接影响崩溃恢复效果?

关键就两个参数,改错一个,可能让“已提交事务丢失”变成现实:

  • innodb_flush_log_at_trx_commit = 1(默认):每次 COMMIT 都调用 fsync() 刷盘 → 最安全,但有性能开销
  • innodb_flush_log_at_trx_commit = 0:只每秒刷一次,崩溃可能丢 1 秒内所有已提交事务
  • innodb_log_file_size:单个 ib_logfile* 大小,默认 48MB。太小会导致频繁 checkpoint,拖慢写入;太大则 recovery 时间变长(要重放更多日志)
  • innodb_log_files_in_group:默认为 2,即 ib_logfile0 + ib_logfile1 循环写。不能直接删文件扩容,必须停库、改配置、删旧文件、重启

常见误操作和坑

很多人以为“只要开了 binlog 就不怕丢数据”,其实完全错误 —— binlog 是 server 层日志,不参与崩溃恢复。真正扛住断电 /kill -9 的,只有 redo log

  • 误删 ib_logfile* 文件?MySQL 启动失败,报错 Cannot find or open table mysql/engine_cost 类似信息 —— 因为 InnoDB 检查不到合法日志头,拒绝启动
  • 升级 MySQL 后没重建 ib_logfile*?可能因格式不兼容导致 recovery 失败或静默跳过,数据实际已损坏
  • innodb_flush_log_at_trx_commit 设成 0 或 2,又没配主从复制 + binlog 备份,等于主动放弃 ACID 中的 D(Durability)
  • 误以为 redo log 能恢复误删表 —— 它只记录页级修改,不存 SQL,也不支持闪回;删表是 DDL,哪怕没提交也立刻落盘,redo log 不管这事

真正要靠 redo log 活命的场景,从来不是“我手抖删了数据”,而是“服务器突然断电”“宿主机宕机”“容器被 OOM kill”。它不聪明,但足够可靠——前提是别动它的刷盘策略和文件结构。

text=ZqhQzanResources