SQL innodb_log_file_size 的 redo log 大小与 crash recovery 时间

1次阅读

innodb_log_file_size过小会拖慢crash recovery,因日志频繁覆盖导致checkpoint频繁推进、recovery需扫描更多分散日志;正确调整需干净shutdown、删除旧日志后重启重建。

SQL innodb_log_file_size 的 redo log 大小与 crash recovery 时间

innodb_log_file_size 设置太小会导致 crash recovery 变慢

mysql 崩溃后重启时,InnoDB 必须重放 redo log 中未刷到数据页的修改,这个过程叫 crash recovery。如果 innodb_log_file_size 太小,日志文件频繁循环覆盖,导致 checkpoint 被迫频繁推进,WAL(write-ahead Logging)压力大,同时 recovery 阶段要扫描更多日志文件、合并更多分散的修改记录,实际恢复时间反而拉长。

  • 典型现象:mysqld 启动卡在 Starting crash recovery... 几分钟甚至十几分钟
  • 不是“越小越快”,而是存在一个拐点:过小会显著拖慢 recovery;过大则浪费磁盘空间、延长 recovery 扫描范围(但影响相对平缓)
  • 官方建议值是总 redo log 容量 ≈ 1–2 小时的写入量,不是单个文件大小 —— 注意是 innodb_log_file_size × innodb_log_files_in_group
  • MySQL 5.6+ 默认 innodb_log_files_in_group = 2,所以调 innodb_log_file_size 时得同步考虑总容量

调整 innodb_log_file_size 的正确操作流程

不能直接改配置重启,InnoDB 会拒绝启动并报错 InnoDB: Error: log file ./ib_logfile0 is of different size。必须清空旧日志、确保干净 shutdown、再重建。

  • 先执行 SET GLOBAL innodb_fast_shutdown = 0,让 InnoDB 完全刷脏页、做 checkpoint
  • 停掉 MySQL:systemctl stop mysqld(或对应服务命令)
  • 手动删除旧日志:rm -f ib_logfile[0-9]*(路径默认在 datadir 下)
  • 修改配置文件中 innodb_log_file_size(例如设为 256M),再启动
  • 首次启动会自动重建日志文件,注意观察 error log 是否出现 Creating ib_logfile* 日志行

怎么判断当前值是否合适

看日志写入节奏和 checkpoint 频率,而不是凭经验拍脑袋。核心指标是 Innodb_os_log_writtenInnodb_buffer_pool_pages_dirty 的变化速率。

  • 每小时执行一次:SHOW GLOBAL STATUS LIKE 'Innodb_os_log_written';,算出每小时增量(单位 bytes),除以 innodb_log_files_in_group 得到单文件应承载的小时写入量
  • SHOW ENGINE INNODB STATUSG 查看 Log sequence numberLast checkpoint at 差值,如果差值长期接近 innodb_log_file_size × innodb_log_files_in_group,说明日志快被写满,checkpoint 被迫追赶,就该调大了
  • 监控工具里重点关注 innodb_log_waits:大于 0 就代表日志写满阻塞事务,必须扩容

MySQL 8.0+ 的特殊注意事项

8.0 开始 innodb_log_file_size 支持在线修改(需配合 ALTER INSTANCE ROTATE INNODB MASTER KEY?不,那是加密密钥),但实际仍不支持热改 —— 官方文档明确写明:「this variable is read-only at runtime」。别信网上某些说能 SET GLOBAL 的误导信息。

  • MySQL 8.0.30+ 引入了 innodb_redo_log_capacity(动态可调),但它替代的是旧机制,启用后 innodb_log_file_sizeinnodb_log_files_in_group 就失效了
  • 启用新机制前必须停机、清空旧日志、初始化新 redo log 存储(innodb_redo_log_capacity 是总容量,单位 bytes)
  • 老版本升级到 8.0 后,默认仍走传统机制,除非你主动迁移;迁移后就不能回退,且备份恢复逻辑也不同

调大 innodb_log_file_size 看似简单,但真正卡住人的往往是 shutdown 不干净、日志残留没删净、或者误以为 8.0 能在线改 —— 这些地方一错,MySQL 直接起不来。

text=ZqhQzanResources