%wa高但CPU利用率低说明I/O等待严重,本质是同步写入(如fsync)导致内核等待磁盘落盘,需用iostat -x 1查%util和await、iotop -oP定位进程,并检查数据库/文件系统/容器的同步配置。

top 里 %wa 高但 CPU 利用率低,基本就是同步写入拖慢了
这说明内核在等磁盘把数据真正落盘(fsync、fdatasync、O_SYNC 等调用),而不是只写进 page cache。常见于数据库事务提交、日志强制刷盘、rsync --sync、或应用自己调用 fsync() 的场景。注意:top 默认不显示 %wa,得按 1 进多核视图,再按 f → 找到 WA 字段回车启用;更省事的是直接用 htop(默认就带这一列)。
iostat -x 1 看 %util 和 await,区分是设备饱和还是单次写太慢
iostat -x 1 比 top 更准,关键看两列:
-
%util持续 >80%:设备被写满,可能是顺序大写或高并发小写压垮了磁盘 -
await明显偏高(HDD >10ms,SSD >1ms),但%util却不高:说明不是吞吐瓶颈,而是某次fsync()或元数据操作卡住了——比如 ext4 上的 journal commit 延迟、XFS 日志满、NFS 服务器响应慢、或存储后端故障
别只盯着 w/s(每秒写次数):同步写压力大时,r/s 可能很低,await 却飙升,因为每次写都得等落盘完成才返回。
iotop -oP 定位哪个进程在狂调 fsync
iotop -oP 能实时看到线程级 I/O,重点找:
Linux 安全审计工具,检查 SSH 配置、开放/监听端口、防火墙规则(ufw/iptables/nftables)、失败登录尝试、sudoers 权限...
- COMMAND 列含
postgres、mysqld、redis-server、java、node等,且IO>列持续高(尤其 WRITE) - 对应 PID 下的线程名(如
postgres: wal writer、java -XX:+UseG1GC)往往暴露了同步刷盘行为 - 如果看到
dd、rsync、cp --sync正在跑,基本就是它
注意:strace -p $PID -e trace=fsync,fdatasync,openat 可验证是否真在频繁调用——但很多 runtime(如 Go 的 os.File.Sync()、Java NIO 的 FileChannel.force())底层走的是 io_submit() 或 preadv2(),strace 不一定捕获全。
查日志和配置,确认是不是 sync 相关参数惹的祸
同步写瓶颈常来自配置项被“无意开猛”:
- PostgreSQL:
synchronous_commit = on+full_page_writes = on+wal_sync_method = fdatasync组合,在 HDD 上极易卡住 - Redis:
appendfsync always或appendfsync everysec但磁盘本身慢,会导致主线程阻塞 - ext4 挂载选项:
data=journal比data=ordered同步开销大得多;barrier=1在无电池缓存的 RAID 卡上会显著拖慢 fsync - 容器场景:
/var/lib/docker所在分区若用了overlay2+ext4+data=journal,docker commit或镜像层写入就会变龟速
真实问题往往藏在“看起来合理”的配置叠加里——比如你只改了 appendfsync,却忘了宿主机文件系统也是 journal 模式,双重 journal 让延迟翻倍。


















