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

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_written 和 Innodb_buffer_pool_pages_dirty 的变化速率。
- 每小时执行一次:
SHOW GLOBAL STATUS LIKE 'Innodb_os_log_written';,算出每小时增量(单位 bytes),除以innodb_log_files_in_group得到单文件应承载的小时写入量 - 用
SHOW ENGINE INNODB STATUSG查看Log sequence number和Last 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_size和innodb_log_files_in_group就失效了 - 启用新机制前必须停机、清空旧日志、初始化新 redo log 存储(
innodb_redo_log_capacity是总容量,单位 bytes) - 老版本升级到 8.0 后,默认仍走传统机制,除非你主动迁移;迁移后就不能回退,且备份恢复逻辑也不同
调大 innodb_log_file_size 看似简单,但真正卡住人的往往是 shutdown 不干净、日志残留没删净、或者误以为 8.0 能在线改 —— 这些地方一错,MySQL 直接起不来。