Linux服务器CPU使用率看起来不高,网站、数据库或容器却明显变慢,top 中的 wa 还在不断升高。这种现象通常说明一部分任务正在等待 I/O,但它并不能直接告诉你是哪块磁盘、哪个进程或哪一层存储出了问题。
下面从系统负载、块设备延迟、进程读写、内核错误和云盘规格几个层面,整理一套可以在生产环境中按顺序执行的排查方法。命令以常见 Linux 发行版为例,高风险修复操作会单独说明边界。

一、先弄清楚:iowait高代表什么
Linux 的 CPU 统计中,iowait 表示 CPU 处于空闲状态、同时系统中存在尚未完成的磁盘 I/O 请求所占的时间比例。它反映的是 CPU 视角下的等待时间,不等于磁盘使用率,也不能单独证明某块磁盘已经跑满。
例如,单线程任务等待一块慢盘时,某个 CPU 的 iowait 可能很高,但设备吞吐量并不大;反过来,支持大量并行请求的 NVMe 或 RAID 即使吞吐量很高,%util 也未必能像传统单盘那样直接解释。判断是否存在存储瓶颈,需要把 CPU、队列、延迟、吞吐和进程行为放在一起看。
二、确认业务变慢是否真的与I/O有关
先记录故障发生的时间、受影响的服务和最近变更,再查看系统负载、CPU 分布、内存和交换分区。不要看到 wa 较高就立即清缓存、重启数据库或删除文件。
uptime
vmstat 1 10
mpstat -P ALL 1 10
free -h
uptime 可以看到负载是否持续升高;vmstat 的 r、b、si、so、bi、bo 和 wa 有助于区分 CPU 排队、不可中断睡眠、交换压力与块设备读写;mpstat 用于确认等待是否集中在部分 CPU。
如果 si/so 持续出现,内存不足导致的换页可能才是根因。此时磁盘繁忙只是结果,应该优先处理内存占用、进程泄漏或容器限制,而不是单纯升级硬盘。
三、用iostat判断是哪块设备慢
安装 sysstat 后,使用扩展设备统计观察至少几十秒,避免只看一次瞬时采样。
# Debian / Ubuntu
sudo apt update && sudo apt install -y sysstat
# RHEL / Rocky Linux / AlmaLinux
sudo dnf install -y sysstat
# 连续观察,每秒刷新一次
iostat -xz 1
r/s、w/s:每秒读写请求数量,可用于观察 IOPS 变化。rkB/s、wkB/s:每秒读写数据量,用于判断吞吐压力。await:I/O 请求从提交到完成的平均时间,通常包含排队和设备处理时间。aqu-sz:平均队列长度。持续增长往往意味着请求到达速度超过处理速度。%util:设备处理 I/O 的忙碌时间比例。传统单盘接近 100% 时常提示饱和,但对 RAID、虚拟盘和具备高并行能力的 NVMe,不能机械地把 100% 当作唯一瓶颈标准。
重点看指标是否同时变化。若 await 和 aqu-sz 持续升高,业务延迟也同步上升,存储排队的可能性较大;若 %util 很高但 await 稳定且业务没有变慢,设备可能只是在持续工作。云服务器还要对照云盘规格中的 IOPS、吞吐上限和突发额度。
四、定位具体是哪个进程在读写
设备层确认异常后,再追踪进程。`pidstat` 适合连续采样,`iotop` 适合现场观察当前活跃 I/O,`/proc//io` 则能查看单个进程累计读写计数。
pidstat -d 1
sudo iotop -oPa
cat /proc/<PID>/io
pidstat -d 1中关注每秒读写量、I/O 延迟字段以及命令名。iotop -oPa仅显示发生 I/O 的任务,并按进程累计统计,适合快速找出持续写盘者。/proc//io的read_bytes和write_bytes更接近实际存储层字节数;rchar、wchar是系统调用层累计值,两者含义不同。读取其他用户进程的数据通常需要相应权限。
短时间抓不到问题时,可以把采样输出写入文件,并与应用日志时间对齐。不要只按瞬时读写速度排序,一次备份、日志轮转或数据库检查点可能持续时间很短,却足以造成明显抖动。
五、区分读取、写入、刷盘和交换压力
不同 I/O 模式对应的处理方法并不相同。大量随机读取可能来自数据库索引缺失、缓存命中率下降或镜像层反复读取;持续写入常见于访问日志、数据库 WAL/redo、消息队列持久化和容器日志;周期性延迟尖峰则可能与脏页回写、快照、备份或文件系统同步有关。
vmstat 1
grep -E 'Dirty|Writeback|Swap' /proc/meminfo
cat /proc/pressure/io
/proc/pressure/io 提供 I/O 压力信息,可以辅助判断任务因 I/O 资源等待而受阻的程度。它与 iowait 的统计口径不同,适合一起观察,而不是互相替代。
六、检查内核日志和存储链路错误
如果延迟突然恶化、设备消失或文件系统转为只读,应立即检查内核日志。硬盘介质、控制器、连接、虚拟化宿主机或云盘后端异常,都可能表现为 iowait 升高。
sudo journalctl -k --since "30 minutes ago"
sudo dmesg -T | grep -Ei 'nvme|scsi|reset|timeout|I/O error|blk_update|ext4|xfs'
看到 timeout、reset、I/O error 或文件系统错误时,不要继续用压测验证性能。先保存日志、确认备份和业务影响,再按设备类型检查 SMART/NVMe 健康状态,必要时联系云服务商。对挂载中的生产文件系统直接执行修复命令可能造成进一步损坏,fsck 应在卸载或救援环境中进行。
七、常见业务场景怎么判断
- 数据库变慢: 对照慢查询、缓冲池命中率、检查点和日志刷盘时间。若单个数据库进程持续产生随机 I/O,应先优化查询和索引,再评估存储。
- Docker主机变慢: 检查容器 JSON 日志、镜像层、构建缓存和 volume。日志无限增长、频繁拉取/解压镜像或多个容器共享一块低规格云盘,都可能形成竞争。
- 日志服务器写入尖峰: 查看日志轮转、压缩和上传任务是否重叠。压缩会同时消耗 CPU 与读写带宽,建议错峰并限制并发。
- 云盘周期性降速: 核对实例与云盘的基准 IOPS、吞吐上限、突发积分、队列深度和监控告警。达到产品上限时,系统内看到的现象可能与本地磁盘饱和相似。
八、建议的处理顺序
- 先确认监控时间窗口和受影响业务,保存
vmstat、iostat、pidstat与内核日志。 - 判断问题是读取、写入、换页、刷盘还是设备错误,并定位到具体块设备。
- 找到产生 I/O 的进程及对应业务任务,暂停非关键备份、压缩、批处理或镜像构建。
- 对日志、数据库和容器分别处理根因,例如设置日志轮转、优化查询、调整缓存或拆分数据盘。
- 确认已触及云盘或硬件能力上限后,再扩容 IOPS、吞吐或更换存储类型。变更前准备备份和回滚方案。
- 处理后用相同采样方式复测,比较业务延迟、
await、队列长度和吞吐,不只看 iowait 是否下降。
九、这些操作容易把问题变复杂
- 只看
top里的 wa 数值,就断定磁盘损坏。 - 直接执行
echo 3 > /proc/sys/vm/drop_caches,把缓存命中率下降造成的额外读盘误当成优化。 - 生产环境中随意
kill -9数据库、强制重启或删除正在写入的日志文件。 - 把
%util=100%作为所有存储设备的统一饱和线,忽略 NVMe、RAID 和虚拟块设备的并行能力。 - 只提升云盘容量,却没有确认该产品的 IOPS、吞吐和实例侧限额是否随容量变化。
总结
iowait 是排查入口,不是故障结论。比较可靠的路径是先确认系统是否真的因 I/O 等待变慢,再用 `iostat` 找到高延迟设备,用 `pidstat`、`iotop` 和 `/proc//io` 定位进程,最后结合内核日志、业务行为和云盘规格判断根因。
排查时保留同一时间窗口的数据,比截取一个瞬时百分比更有价值。处理顺序也应从暂停非关键任务、降低并发开始,再进入数据库优化、日志治理、存储扩容或硬件故障处置。
参考资料
- Linux Kernel Documentation:/proc/stat 与 CPU 时间统计
- sysstat:iostat 命令手册
- sysstat:pidstat 命令手册
- sysstat:mpstat 命令手册
- Linux man-pages:vmstat(8)
- Linux man-pages:proc_pid_io(5)
- iotop 官方项目文档
- Linux Kernel Documentation:PSI 压力停顿信息
本文核验日期:2026年8月26日。Linux 发行版、sysstat 版本、虚拟化平台和云盘产品不同,字段名称及行为可能存在差异,请以实际系统手册和服务商文档为准。




