必须用 iostat -dx 1,因其能直接显示 r_await、w_await(毫秒级延迟)和 aqu-sz(队列长度),而默认 iostat 缺失关键延迟指标;HDD 超 10ms、NVMe 超 0.5ms 即预警,aqu-sz 持续 >1 表明排队而非设备慢。

直接看 iostat -dx 1,别先跑 top 或查日志——磁盘 I/O 延迟就明晃晃写在 r_await、w_await 和 aqu-sz 里。
为什么必须用 iostat -dx 1 而不是默认 iostat
不加 -x 的 iostat 只输出吞吐量(rkB/s、wkB/s)和简单计数(r/s、w/s),完全看不到延迟。而真实卡顿来自请求排队或设备响应慢,不是“写得多”,而是“等得久”:
-
-d:只显示磁盘行,过滤掉 CPU 行干扰判断 -
-x:启用扩展字段,r_await和w_await才真正可用(单位毫秒) -
1:每秒刷新,避免看“自启动以来平均”这种失真值 - HDD 超
10ms、SATA SSD 超1ms、NVMe 超0.5ms就该警觉;aqu-sz持续 >1表示请求在排队,不是设备慢
r_await 高但 w_await 正常,说明什么
这是典型的读密集型瓶颈,不是磁盘整体坏,而是读路径被压垮:
- 数据库全表扫描、备份脚本全量读取、日志轮转时
gzip解压大文件都可能拉高r_await - 如果
r/s很高但rkB/s很低,大概率是大量小读(如 4KB),触发频繁寻道或页缓存失效 - 配合
iotop -oPa看哪个进程在读,再用lsof -p PID查它打开的文件——重点盯/var/lib/mysql/下的 ibd 文件或归档日志 - 注意:
r_await高 +avgqu-sz也高 → 排队严重;r_await高 +avgqu-sz低 → 设备响应慢(比如 HDD 物理老化)
w_await 爆高但 w/s 很低,怎么排查
这说明不是吞吐问题,而是少量写请求卡在队列里出不去,常见于同步小写场景:
- 典型诱因:
fsync()/msync()调用、XFS 日志刷盘阻塞、ext4 启用barrier后等待存储确认 -
w_await>20ms且远高于svctm(哪怕svctm是估算值)→ 基本可断定是排队,不是设备慢 - 检查队列深度:
cat /sys/block/nvme0n1/queue/nr_requests,若aqu-sz>nr_requests × 0.7,说明上层压入太快 - NVMe 设备必须关调度器:
echo none > /sys/block/nvme0n1/queue/scheduler,否则mq-deadline会强制串行化请求
当 iostat 显示延迟高,但 iotop 找不到罪魁祸首
这时候 I/O 根本没走进程路径,而是藏在内核后台线程或硬件链路里:
-
iotop -o会漏三类行为:短时高频小写(每秒几千次write(2))、mmap回写脏页、管道/套接字间接落盘(如rsyslog转发日志) - 先跑
pidstat -d 1 3对比累计 I/O,若仍安静,立刻查/proc/diskstats第 9 列(aveq,加权队列长度)是否真实堆积 - 运行
dmesg | grep -i "nvme\|ata\|error\|timeout":PCIe AER 错误、ACPI 电源状态异常、NVMe 控制器固件重试都会导致延迟毛刺,iostat完全不体现 - 最常被忽略的一点:
await高 ≠ 磁盘坏了,它可能只是上层调度器配错了、队列深度没对齐、甚至 BIOS 中 PCIe ASPM 被错误启用


















