Redo log空间不足会强制同步触发checkpoint以腾出日志空间,表现为Log checkpoint age飙升、脏页骤降、IO突增和TPS下跌;innodb_flush_log_at_trx_commit=1加剧该压力,而磁盘I/O瓶颈会进一步恶化刷盘阻塞。

redo log space不足会强制触发checkpoint
大并发写入时,redo log buffer 和磁盘上的日志文件都在快速被填满。InnoDB 必须保证 write pos(当前写入位置)和 checkpoint(已刷盘到数据页的LSN位置)之间留有足够空间,否则无法继续写日志——这就像环形跑道上,后面的人快追上前面的人了,必须让前面的人先跑完一段再回头接应。一旦 Log checkpoint age 接近 innodb_redo_log_capacity(或旧版本的 innodb_log_file_size × innodb_log_files_in_group),InnoDB 就会主动、同步地推进 checkpoint,把脏页刷到磁盘,腾出 redo log 空间。
为什么是“同步”而不是后台异步?
因为此时不是“等一等再处理”,而是“不立刻刷就写不下去”。InnoDB 在以下任一条件满足时会进入同步刷盘模式:
-
Log checkpoint age > 0.8 × innodb_redo_log_capacity(默认阈值,由innodb_max_dirty_pages_pct和内部算法联动) - 事务提交过程中发现 redo log 空间即将耗尽,且后台线程来不及响应
- 遇到大事务(如单条 UPDATE 影响百万行),一次生成大量 redo,瞬间拉高 checkpoint age
这时你可能在 SHOW ENGINE INNODB STATUS 的 LOG 段看到 Log checkpoint age 值飙升,同时 Dirty pages 数量骤降——说明 Buffer Pool 正在被强制刷新,IO 突增,TPS 下跌。
innodb_flush_log_at_trx_commit=1 加剧同步刷盘压力
这个参数本身不直接触发 checkpoint,但它会让每次事务提交都调用 fsync(),把日志从 OS cache 落盘。在高并发下,频繁 fsync() 会拖慢日志写入速度,间接抬高 Log sequence number 的推进节奏,使 write pos 更快逼近 checkpoint,从而更早触达空间阈值。换句话说:innodb_flush_log_at_trx_commit=1 是“推手”,innodb_redo_log_capacity 过小才是“导火索”。
容易被忽略的隐性瓶颈:磁盘 I/O 吞吐跟不上 checkpoint 需求
即使你把 innodb_redo_log_capacity 设得足够大,如果底层存储(比如机械盘、低配云盘、共享 SAN)的随机写 IOPS 不足,checkpoint 所需的脏页刷盘就会排队阻塞。此时你会观察到:
- 事务提交延迟(
innodb_log_waits计数器上升) -
SHOW ENGINE INNODB STATUS中Pages flushed速率远低于Pages made young - 系统级监控显示
iowait持续高于 30%
这不是配置错了,而是物理层已经成了木桶最短那块板——调大日志容量或改参数都治标不治本,得换更快的存储或拆分写负载。


















