数据库高并发引发磁盘I/O瓶颈本质是写放大、刷盘频繁或缓存失效;排查需分层:先确认是否真实IO问题(看%wa、%util、await、rKB/s/wkB/s),再判读/写压力,最后分析数据库行为。

数据库高并发引发磁盘 I/O 瓶颈,本质是写放大、刷盘频繁或缓存失效导致大量请求穿透到磁盘。排查不能只盯着“哪个进程在写”,而要分层定位:先确认是不是真 IO 问题,再看是读压还是写压,最后落到数据库行为本身。
第一步:确认是否为真实磁盘 IO 瓶颈
别急着查 MySQL,先排除误判:
- 运行 top,观察 %wa(iowait)是否持续高于 30%;若低于 10%,大概率不是 IO 问题
- 执行 iostat -x 1,重点关注目标数据盘(如 /dev/nvme0n1 或 /dev/sda)的三项指标:
– %util ≥ 80%(SSD 可放宽至 90%,但 await 同步看)
– await > 50ms(机械盘 > 20ms 就需警惕)
– wkB/s 或 rKB/s 明显高于历史基线(比如平时写 20MB/s,现在冲到 120MB/s) - 注意:如果 %util 高但 await 很低(如
第二步:区分读压还是写压,缩小数据库行为范围
用 iostat -x 1 连续观察几秒,看主导项:
- 写压主导:wkB/s 远高于 rkB/s,且 %util 和 await 同步飙升 → 关注 binlog 刷盘、redo log 写入、临时表落盘、慢查询排序/聚合写磁盘
- 读压主导:rkB/s 高 + await 高 + buffer hit rate 下降(可通过 MySQL 的 SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_read%' 计算)→ 表明缓存不足,大量物理读
- 读写混合但无明显偏向:可能是大量小文件操作(如 MySQL 的 .ibd 文件随机访问)、元数据锁争用触发频繁 fsync,或备份/归档任务干扰
第三步:定位数据库内部具体诱因
找到高 IO 的 mysqld 进程后,深入其行为:
- 用 pidstat -d -p $(pgrep mysqld) 1 查看该进程每秒读写字节数,确认是否与 iostat 匹配
- 查 MySQL 当前活跃语句:
SELECT * FROM information_schema.PROCESSLIST WHERE COMMAND != 'Sleep' ORDER BY TIME DESC LIMIT 10;
重点关注状态为 Sending data(大结果集传输)、Sorting result、Creating sort index、Copying to tmp table 的语句 - 检查 InnoDB 状态:
SHOW ENGINE INNODB STATUS\G,重点看 FILE I/O 部分的 pending reads/writes,以及 LOG 部分的 log writes、fsyncs 次数 - 查看临时表使用:
SHOW GLOBAL STATUS LIKE 'Created_tmp%';
若 Created_tmp_disk_tables 增速快,说明排序/JOIN 落盘严重
第四步:验证与收敛(避免“看起来像”)
有些现象容易误导,需交叉验证:
- iotop 显示 mysqld 占 IO 99%,但 lsof -p 查不到大文件写入? → 很可能在写 page cache(如 redo log buffer 刷盘前的 memcpy),或使用 Direct I/O(绕过缓存,但不显式打开文件)
- IO 高发时段恰好是定时备份时间? → 用 ps aux | grep -E "(mysqldump|mydumper|xbstream)" 确认是否有备份进程在后台运行
- 应用刚上线或 SQL 改写后出现? → 对比慢日志(slow query log)中新增的高 Rows_examined / Rows_sent 语句,特别是含 GROUP BY、ORDER BY、子查询、UNION 的
- 磁盘硬件本身异常? → 用 smartctl -a /dev/sda 查健康状态,用 iostat -x 1 观察 rrqm/s(读合并)和 wrqm/s(写合并)是否异常高(可能预示驱动或固件问题)


















