SSD上innodb_io_capacity和innodb_io_capacity_max必须按fio实测随机写IOPS的0.7~0.8倍及1.5~2倍成对设定,否则参数无效;须先关闭I/O调度器(NVMe设none、SATA SSD设noop),并同步配置innodb_flush_neighbors=0、innodb_write_io_threads≥4、innodb_lru_scan_depth≥2048。

innodb_io_capacity 和 innodb_io_capacity_max 必须按实测 IOPS 设,否则参数再调也是空转。
先关掉 Linux I/O 调度器,再谈 MySQL 参数
SSD 不需要寻道,cfq 或 deadline 调度器反而引入排队和延迟。不关调度器,后面所有 InnoDB 参数优化都打七折。
- NVMe 盘:确认
/sys/block/nvme0n1/queue/scheduler输出含[none],没就执行echo none > /sys/block/nvme0n1/queue/scheduler - SATA SSD:对应设备名(如
sda)下应为[noop],设法切过去 - 云主机或容器里可能无法直接改,得查宿主机是否已配好;改完用
fio对比压测,await 明显下降才算生效
用 fio 实测随机写 IOPS,别信标称值
innodb_io_capacity 的值不是拍脑袋定的,它必须基于你这块 SSD 在数据库负载下的真实随机写能力。dd 或顺序读写测试毫无参考价值。
- 跑这个命令:
fio --name=randwrite --ioengine=libaio --rw=randwrite --bs=4k --iodepth=64 --runtime=60 --time_based --direct=1 --filename=/path/to/ssd/testfile - 重点看输出里最后一行的
iops值(不是bw),取最后 30 秒稳定值 - 消费级 NVMe 常见 8–15 万,SATA SSD 多在 2–5 万;若
%util == 100%且await > 5ms,说明当前配置已压满磁盘,不是参数问题而是 IO 真瓶颈
innodb_io_capacity 和 innodb_io_capacity_max 要成对设
这两个值必须一起调,且比例要稳。单独改 innodb_io_capacity 几乎无效——InnoDB 后台刷脏页、合并 change buffer 的节奏受二者共同约束。
-
innodb_io_capacity = 实测 IOPS × 0.7~0.8(留余量),例如实测 115000 → 设85000 -
innodb_io_capacity_max = innodb_io_capacity × 1.5~2,例如85000 → 127500~170000;设为 0 或缺省会触发不可控的自动推算,线上严禁 - 设太高:出现
log file is full、Waiting for query cache lock类等待飙升,本质是 redo 循环跟不上刷盘速度 - 设太低:脏页积压,
Pages flushed曲线出现 15 分钟周期性毛刺(日志切换强制 flush)
配套必调的 3 个 InnoDB 参数
只调 innodb_io_capacity 是纸上谈兵。SSD 的高并发特性要求线程、邻近页策略、LRU 扫描深度同步放开。
-
innodb_flush_neighbors = 0:HDD 时代为减少寻道合并邻页,SSD 上纯属制造无效 IO,关了稳提 15%+ 写入吞吐 -
innodb_read_io_threads和innodb_write_io_threads各设为4~8(默认都是 4),让 IO 队列不饿着 -
innodb_lru_scan_depth从默认1024提到2048或4096:SSD 响应快,可以更激进地扫描 LRU 链表,避免缓存淘汰滞后
innodb_flush_neighbors = 0 —— 它不显眼,但不开的话,哪怕 IOPS 测出来 12 万,MySQL 实际写入也卡在 2 万左右,而且你很难一眼定位到这行配置上。


















