Innodb_buffer_pool_wait_free非零是卡在等待空闲页的直接信号,需结合脏页比例、fsync/write比值及INNODB STATUS中LOG/SEMAPHORES等线索综合诊断刷盘瓶颈。

查 Innodb_buffer_pool_wait_free 是否非零
这个状态值是判断是否卡在等待空闲页的最直接信号。只要它大于 0,就说明有线程正在阻塞等待 buffer pool 释放出干净页——不是没内存,是没“能用的页”。
执行:SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_wait_free';
如果返回值持续 > 0(尤其在业务高峰期反复跳变),基本可以锁定问题方向。
注意:这个计数器是累计值,不能只看当前值,要配合采样间隔观察增长速率。比如 30 秒内从 1200 增到 1250,说明平均每秒有 1.6 次等待,已经非常危险。
结合 Innodb_buffer_pool_pages_dirty 看脏页积压程度
单看等待 free 页不够,得知道“为什么没 free 页”——大概率是脏页刷得太慢,占着位置不走。
执行:SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_pages_dirty';
再查总页数:SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_pages_total';
算比例:如果 Innodb_buffer_pool_pages_dirty / Innodb_buffer_pool_pages_total 长期 > 70%,就是典型脏页堆积。
常见诱因:
• innodb_io_capacity 设得太低(SSD 还设 200)
• innodb_log_file_size 太小,导致 redo log 频繁写满,触发强制同步刷脏页
• innodb_buffer_pool_instances = 1 且 buffer pool 很大(如 32GB+),刷脏页锁争用严重
验证刷盘节奏是否被压制:对比 Innodb_data_fsyncs 和 Innodb_data_writes
如果脏页一直在写入 buffer pool,但 fsync 落盘跟不上,就会越积越多。
执行:SHOW GLOBAL STATUS LIKE 'Innodb_data_fsyncs'; 和 SHOW GLOBAL STATUS LIKE 'Innodb_data_writes';
算比值:Innodb_data_fsyncs / Innodb_data_writes。正常应该接近 0.8~1.0;如果长期低于 0.3,说明 write 多、fsync 少,刷盘被后台线程主动压速或系统 IO 调度卡住。
这时再查:SHOW VARIABLES LIKE 'innodb_io_capacity'; —— SSD 环境下低于 1000 就值得怀疑。
别漏掉 SHOW ENGINE INNODB STATUS\G 里的隐性线索
这个命令输出里藏着关键上下文,光看 status 变量容易误判。
重点搜:
• “LOG” section:看 Log sequence number 和 Last checkpoint at 的差值。如果超过单个 innodb_log_file_size 的 80%,说明 checkpoint 跟不上,redo log 快满了,马上会连坐刷脏页。
• “SEMAPHORES” section:找 buf_flush_list_mutex 等待,确认是不是 buffer pool instance 锁争用导致刷页线程卡死。
• “TRANSACTIONS” section:看有没有长事务一直 hold 着 undo log,间接拖慢 purge 和刷脏进度。
真正卡在 free buffer 阶段的问题,往往不是 SQL 写得不好,而是底层刷新机制被参数或硬件能力卡住了咽喉。很多人调完 innodb_io_capacity 就以为搞定,却忘了检查 innodb_buffer_pool_instances 是否匹配 buffer pool 大小,或者忽略 redo log 总大小是否撑不起当前写入压力——这些点一旦漏掉,问题会反复出现。











