Linux 磁盘 IO 等待过高 iowait 怎么排查优化

文章导读
遇到 iowait 高的问题,我通常先把 CPU、内存、磁盘三张表同时抓下来,先确认现象,再定位进程。因为 iowait 高只是 CPU 等待 IO 完成的时间占比,不是磁盘利用率本身,有时候问题根本不在磁盘。
📋 目录
  1. 先确认现象:iowait 高不等于磁盘利用率高
  2. 容易误判的情况:别只盯磁盘
  3. 定位到具体进程和打开的文件
  4. 从应用层和文件系统层优化
  5. 每一步都要留回滚余地
  6. 后续维护:定期检查基础状态
A A

遇到 iowait 高的问题,我通常先把 CPU、内存、磁盘三张表同时抓下来,先确认现象,再定位进程。因为 iowait 高只是 CPU 等待 IO 完成的时间占比,不是磁盘利用率本身,有时候问题根本不在磁盘。

先确认现象:iowait 高不等于磁盘利用率高

在系统卡顿的时候,我第一件事是看 vmstat 的输出。当系统负载升高时,先通过 vmstat 查看 r 和 b 列。如果 r(运行队列)不高但 b(阻塞队列)持续有进程,且 us 和 sy 不太高而 wa 偏高,那么大概率是磁盘 IO 等待造成的。此时再运行 iostat -x 1 观察各磁盘的 %util、await 和 svctm。若 %util 接近 100% 但 await 不大,说明设备已饱和;若 %util 较低但 await 较大,则可能磁盘本身响应慢或存在队列延迟。注意 iowait 是 CPU 层面的指标,反映的是 CPU 空闲等原因,而不是磁盘利用率,两者不能直接画等号。

所以我会先记录 wa 和 CPU 各态,再看具体设备。避免一开始就冲着坏道去。

容易误判的情况:别只盯磁盘

排查 iowait 时,有几个方向最容易看走眼。比如内存不足触发的换页,也会让 wa 升高,但问题其实在内存。iSCSI 或 NFS 这类网络存储,延迟高时同样表现为 iowait 高,但根因在网络。另外,raid 卡写缓存关闭后,写性能骤降,可 iostat 的 %util 不一定高,因为设备层看到的 IO 和服务器的 IO 不是同一层。ext4 的 data=ordered 模式会在日志提交时集中写,小文件多时也可能拉高等待。所以不能只盯着磁盘的读数,要结合其他指标看趋势。

Linux 磁盘 IO 等待过高 iowait 怎么排查优化

定位到具体进程和打开的文件

确认 iowait 高之后,接下来的动作是找到是谁在读写。定位到具体进程和文件很重要。使用 pidstat -d 1 可以看到每个进程每秒的读、写字节数和 IO 操作数,从而找到 IO 大户。也可以配合 iotop 观察实时 IO 排行,但 iotop 需要 root 权限,且在繁忙系统上会增加额外开销。另一个思路是用 lsof 查看疑似进程打开的文件,结合文件系统确认是否是日志、临时文件或数据文件。如果进程已经消失,可以用 sar -d 查看历史记录的设备忙碌率和平均请求大小,帮助推断当时的 IO 模式。这些命令都不需要重启服务,可放心在测试环境执行。

我通常会这样组合使用:

vmstat 1 5
iostat -x 1 3
pidstat -d 1 5

如果看到某个进程持续有大块读或大量小写,再进入它的工作目录确认。

Linux 磁盘 IO 等待过高 iowait 怎么排查优化

从应用层和文件系统层优化

优化思路应先从应用层入手。检查是否有不必要的大文件拷贝、频繁 fsync、随机小 IO 多而无批量合并。对于数据库类应用,可调大 redo log 或让 checkpoint 更平滑;对于日志类,可考虑异步写或缓冲批量写。文件系统层面,可尝试调整 mount 参数,比如 noatime、barrier 或 nobarrier 的取舍,但 nobarrier 可能带来数据一致性风险,仅适合可容忍异常重启丢失部分写入的场景。若条件允许,把随机读多的数据迁到 SSD,或用 bcache 缓存。不要一开始就买新硬件,先观察系统的 IO 类型和平均队列深度。

举个例子,如果确认是大量随机小 IO,而数据库的 redo 日志频繁刷盘,我先看是否能把日志文件放到单独的磁盘或 SSD,或者调整日志缓冲大小。文件系统层的调整,我会先在测试环境验证。

Linux 磁盘 IO 等待过高 iowait 怎么排查优化

每一步都要留回滚余地

任何优化都带有风险边界。调整 io scheduler,比如从 cfq 改到 noop 或 deadline,可能降低低延迟,但可能牺牲多任务公平性。修改文件系统日志模式、关闭 barrier 或变更挂载参数,都会影响重启后的数据一致性。所以我每次只改一项参数,改之前先备份系统盘和重要数据,并在非高峰时段进行。如果是线上数据库,我会先做完整备份,还要准备好回滚用的原参数记录。

后续维护:定期检查基础状态

除了性能监控,还要关注硬件健康。smartctl -a /dev/sda 可以看到 Reallocated_Sector_Ct 和 Current_Pending_Sector 等关键值,这些持续升高往往意味着坏道风险。软件 RAID 可以看 /proc/mdstat,硬件 RAID 要用阵列卡自带工具查看缓存策略。文件系统碎片化在 ext4/xfs 上通常影响不大,但日志文件过大会拖累读写,需要定期清理。另外,/proc/diskstats 可以提供原始计数,用 iostat 对照着看能发现统计偏差。这些健康检查适合在业务低峰期做,避免额外读取加重 IO。

最后说一句:iowait 高不是单一的磁盘问题,我每次排查都会记录下 vmstat、iostat 和进程信息,再逐步缩小范围。把现象和进程绑定了,才谈得上优化。