ssd上mysql磁盘io持续高负载主因是innodb_io_capacity未匹配ssd真实能力且未协同innodb_adaptive_flushing(需on)、innodb_io_capacity_max(设为2~3倍)及linux调度器(应设elevator=none),单独调参无效。

SSD上MySQL磁盘IO持续高负载,大概率不是硬盘不行,而是innodb_io_capacity设错了——它没对上SSD的真实能力,反而让InnoDB刷脏页的节奏乱了。
为什么调了innodb_io_capacity还是IO高?
这个参数单独调没用,它必须和两个配套机制一起生效:
-
innodb_adaptive_flushing必须为ON,否则InnoDB退化成固定速率刷脏,innodb_io_capacity几乎不参与决策 -
innodb_io_capacity_max得设成innodb_io_capacity的 2~3 倍(比如前者 4000,后者至少 8000),否则突发写入时无法弹性提速,脏页堆到临界点才紧急刷盘,IO瞬间打满 - Linux I/O调度器没关,SSD上还跑
cfq或deadline,会引入额外排队和延迟,iostat -x 1里能看到aqu-sz异常升高、w_await飘到 10ms 以上
SSD该设多少?别抄标称IOPS
innodb_io_capacity不是硬盘包装盒上写的“50000 IOPS”,它是InnoDB后台任务(刷脏页、合并插入缓冲)能稳定占用的随机写IOPS上限。设太高,IO被后台占满,查询响应变卡;设太低,脏页越积越多,最终触发强制刷盘,Buffer Pool命中率断崖下跌。
- SATA SSD:从
2000起步,用iostat -x 1观察:%util长期 w_await 4000~6000 - NVMe SSD(如腾讯云IT3本地盘):实测稳定随机写IOPS常超10K,初始值可设
8000,再根据Innodb_buffer_pool_pages_dirty是否平稳回落微调 - 云盘(AWS gp3 / 阿里云ESSD):查厂商文档给的「随机写IOPS」,取 70% 作为起点,比如标称 16000 → 设
11200
调完IO高没降,先看这几个状态变量
别急着改回原值,用这几条命令快速定位是节奏问题还是资源真不够:
-
SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_pages_dirty';—— 如果忽高忽低(比如几分钟内从 1000 涨到 8000 又暴跌),说明innodb_io_capacity_max卡太死,或innodb_adaptive_flushing实际是OFF -
SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_read_requests';和Innodb_buffer_pool_reads—— 算比值,低于 99.5% 就得警惕,可能是刷得太猛把热页踢出了Buffer Pool -
SHOW ENGINE INNODB STATUS\G→ 看 LOG 部分的 “Log sequence number” 和 “Last checkpoint at” 差值,如果 >innodb_log_file_size× 0.8,说明checkpoint跟不上,得同步调innodb_io_capacity和innodb_io_capacity_max
容易被忽略的系统层开关
MySQL参数调得再准,底层OS还在用机械盘那一套调度逻辑,SSD性能就废了一半:
- Linux默认可能仍启用
cfq调度器,需永久关闭:/etc/default/grub中GRUB_CMDLINE_LINUX加elevator=none,再执行update-grub && reboot - 文件系统挂载选项要配
nobarrier(XFS)或barrier=0(ext4),但仅限有BBU/FBWC RAID卡或UPS保障的环境,否则断电风险陡增 -
innodb_lru_scan_depth默认 1024 太浅,SSD高IOPS下容易误淘汰热页,建议提到2560~4096
真正卡住的往往不是innodb_io_capacity本身,而是它和innodb_adaptive_flushing、innodb_io_capacity_max、Linux调度器这三者的协同关系。一个参数动了,另外三个没跟上,IO负载只会更毛刺。











