ssd环境设为60~75、hdd设为50~60、高频写入可试75~80,但需同步调优innodb_lru_scan_depth、innodb_io_capacity等耦合参数并验证刷页平稳性。

innodb_max_dirty_pages_pct 设多少才不抖
别设成 5 或 10 —— 这是最常见的误操作,反而会让刷页更抖、查询更卡。这个参数不是“脏页危险阈值”,而是后台刷页节奏的触发开关。设太低(比如 20 或 30),InnoDB 会在脏页刚超线时就小批量刷一次,导致刷页线程高频唤醒、打断查询 I/O 调度。
- SSD 环境:设为
60~75,给后台留出平滑刷页窗口,避免毛刺 - HDD 环境:设为
50~60,防止刷页争抢本就紧张的磁盘带宽 - 高频写入场景(如日志表密集写):可试探性设到
75~80,但必须同步观察Innodb_os_log_pending_fsyncs是否持续攀升 - 别在线
SET GLOBAL innodb_max_dirty_pages_pct = X后就认为生效——已有脏页仍按旧策略处理,新策略只影响后续刷页决策
为什么调了 innodb_max_dirty_pages_pct 却没效果
常见原因不是参数没改对,而是被其他隐性开关卡住了节奏:
-
innodb_lru_scan_depth默认是1024,高并发写入下容易引发 LRU 链表扫描锁争用,拖慢整个刷脏流程;SSD 可压到256或512,HDD 建议128或更低 -
innodb_io_capacity没匹配磁盘真实能力:SSD 实测随机写 IOPS 是3000,却还用默认200,再调innodb_max_dirty_pages_pct也没用 -
innodb_adaptive_flushing关闭时,刷页完全依赖脏页比例;开启后会结合 redo log 生成速率动态调整,更适合写入波动大的业务 - NUMA 绑定失效:
numastat -p $(pgrep mysqld)显示numa_hit90%,说明刷页时从远端节点分配内存,引发跨 NUMA 访问和换页风暴
innodb_flush_neighbors 在 SSD 上必须关
这个参数控制刷一个脏页时是否顺带刷物理相邻的脏页。在 HDD 上能合并随机写为顺序写,但在 SSD 上毫无收益,反而浪费 I/O 带宽、拉高延迟。
- 动态关闭:
SET GLOBAL innodb_flush_neighbors = 0 - 确认存储类型:
cat /sys/block/*/queue/rotational,输出0表示 SSD - MySQL 5.7 默认开启该参数,SSD 环境务必手动关掉
验证是否真起作用,别只看变量值
改完配置后,不能只跑 SHOW VARIABLES LIKE 'innodb_max_dirty_pages_pct' 就收工。真正要看的是:
-
Innodb_pages_written每秒增量是否更平稳(抖动下降 20%+ 且业务无延迟上升) -
Innodb_os_log_pending_fsyncs是否不再持续攀升(说明刷脏没滞后) -
numastat -p $(pgrep mysqld)中numa_hit是否 ≥90%(排除 NUMA 绑定失效干扰) -
SHOW ENGINE INNODB STATUS\G中BUF_POOL_LRU_SCAN_DEPTH单次扫描耗时是否 10ms
innodb_lru_scan_depth 后,若 innodb_io_capacity 还卡在默认值,刷脏总量可能跟不上写入速度;而盲目拉高 innodb_io_capacity 却不调低 innodb_lru_scan_depth,只会让 CPU 更忙、IO 更乱。











