直接看%util超过70%就得排查,因持续>70%且await>10ms即表明磁盘io瓶颈;需用top查%wa>30%、iostat -x 1看%util与await、iotop -o确认mysqld主导io、df -h检查磁盘空间是否超90%,并结合innodb_buffer_pool_reads>100/秒等指标综合判断。

直接看 %util 超过 70% 就得动手查,别等它到 100% 才反应——这时候 MySQL 很可能已经在卡住新连接了。
怎么确认是磁盘IO拖慢了MySQL
先别进 MySQL,系统层就能快速排除干扰:
-
top看%wa:持续 >30% 说明 CPU 正在干等磁盘,不是 CPU 或内存瓶颈 -
iostat -x 1看%util和await:%util长期 >70% +await>10ms 是典型 IO 瓶颈信号 -
iotop -o过滤活跃 IO 进程:确认是不是mysqld在主导读写,而不是 backup、rsync 或其他进程 - 用
df -h检查 MySQL 数据目录所在磁盘是否快满(Use%>90% 会触发内核级写阻塞,%util会虚高)
为什么 iotop 显示 mysqld 占 IO,但慢查询日志没报慢SQL
常见错觉:以为“没慢 SQL”就等于“没 IO 问题”。其实大量合法但低效的 IO 操作根本不会进慢日志:
- 全表扫描(
sys.statements_with_full_table_scans可查) - 临时表落盘:
ORDER BY、GROUP BY、DISTINCT超出tmp_table_size/max_heap_table_size时会写磁盘 - Buffer Pool 不足导致频繁换页:查
SHOW ENGINE INNODB STATUS\G里的Innodb_buffer_pool_reads(每秒从磁盘读页数),持续 >100 就危险 - Redo Log 刷盘太勤:
innodb_flush_log_at_trx_commit=1+ 小事务高频提交,iotop里能看到mysqld频繁写ib_logfile0
哪些 MySQL 参数调不对会让 IO 直接拉满
这些配置项不看文档乱设,IO 压力翻倍是常态:
-
innodb_buffer_pool_size:设太小(比如只占物理内存 20%)→ 缓存命中率 Innodb_buffer_pool_reads -
innodb_io_capacity和innodb_io_capacity_max:SSD 却按 HDD 设(如仍设 200)→ 后台刷脏太慢 → Buffer Pool 积压 dirty page → 触发同步刷盘阻塞前台 -
sync_binlog=1+innodb_flush_log_at_trx_commit=1:双保险变成双写放大,尤其写密集场景,IO 请求量可翻 3–5 倍 -
innodb_flush_method:设成async_unbuffered(默认值)在某些文件系统(如 ext4)下会引发额外拷贝,改O_DIRECT可降 IO 延迟
查到 IO 高源头后,优先动哪块
别一上来就调参数。按实际影响排序:
- 先砍掉明显低效操作:用
sys.schema_tables_with_full_table_scans找出扫全表的表,加索引或改查询 - 再看临时表:监控
Created_tmp_disk_tables,调大tmp_table_size和max_heap_table_size(需两者一致) - 最后动核心参数:
innodb_buffer_pool_size必须调,但别一次调到 80%,先加 10G 观察 24 小时Innodb_buffer_pool_read_requests/Innodb_buffer_pool_reads比值 - 日志刷盘策略:仅当业务能容忍秒级数据丢失时,才考虑
innodb_flush_log_at_trx_commit=2;sync_binlog改成 100–1000 更稳妥
真正麻烦的从来不是 %util 数值本身,而是它背后混合了 SQL、缓存、日志、硬件四层耦合——单点优化容易反复打脸,得盯着 await、avgqu-sz、Innodb_buffer_pool_reads 这几个数一起变,才算稳住。











