来源:赵楠 | 发布日期:2026-07-30
磁盘 IO 排查实战
服务器变慢,CPU 正常、内存正常——凶手其实是磁盘 IO。很多人"查了磁盘没问题",是因为只查了空间没查性能。
磁盘问题的三种类型
| 问题类型 | 症状 | 排查工具 |
|---|---|---|
| 磁盘空间不够 | 写文件报错、日志停止写入 | df -h |
| 磁盘速度太慢 | 服务响应慢、iowait 高 | iostat |
| 某个进程在疯狂读写 | 磁盘灯狂闪、I/O 负载高 | iotop |
绝大多数人只会第一种——df -h 看空间。但服务器变慢通常是第二、三种,df 对这两种完全看不出来。
iostat:磁盘版"心电图"
iostat -x 2
输出示例:
Device r/s w/s rkB/s wkB/s await r_await w_await %util
sda 0.5 180.3 8.0 2880.0 126.4 8.2 127.1 94.2
六个关键指标
| 指标 | 含义 | 核心判断 |
|---|---|---|
| %util | 磁盘忙碌占比 | 见下方陷阱 |
| await | IO 请求平均等待时间 (ms) | 真正的瓶颈指标 |
| r_await / w_await | 读/写请求平均等待时间 | 区分读/写瓶颈 |
| r/s, w/s | 每秒读写次数 (IOPS) | 结合设备上限判断 |
| rkB/s, wkB/s | 读写吞吐量 | 结合带宽上限判断 |
| avgqu-sz | 平均队列长度 | > 2 有积压,> 8 严重阻塞 |
%util 的陷阱
%util = 94.2 表示每 100ms 中磁盘有 94.2ms 在处理 IO。
%util 100% ≠ 磁盘坏了,也不等于性能见底。
- 机械硬盘:
%util接近 100% 确实饱和 - SSD/NVMe:可同时处理上千个 IO 请求,
%util 100%只说明"每秒都有请求在跑",不代表跑不动
判断磁盘是否真瓶颈,必须结合 await。
await:真正的瓶颈指标
await 是 IO 请求从发出到完成的平均等待时间(毫秒)。
| 存储类型 | 正常范围 | 异常阈值 |
|---|---|---|
| 机械硬盘 (HDD) | 5–20ms | > 50ms |
| SATA SSD | 0.1–1ms | > 10ms |
| NVMe SSD | 0.05–0.5ms | > 5ms |
类比:%util 是收银台有没有在工作,await 是顾客排队要等多长时间。收银台一直在转(%util 高)但队伍很长(await 高),才是真正的瓶颈。
IOPS vs 带宽:两个不同维度
典型误解: "磁盘带宽还没用满,应该不慢?"
不一定。 带宽和 IOPS 是两个维度:
- 高带宽、低 IOPS:大卡车运大批货
- 高 IOPS、低带宽:大量快递员送小包裹
机械硬盘 IOPS 通常只有 100–200 次/秒(受限于磁头物理移动)。数据库随机读写是大量小 IO——每次只读几 KB,一秒请求 200 次就把 HDD 打满,但带宽可能只用了几 MB/s。
SSD 对数据库提升巨大的原因:NVMe SSD IOPS 能到几十万次,彻底解决随机 IO 瓶颈。
iotop:找出"磁盘杀手"进程
iostat 告诉你磁盘在被打,iotop 告诉你是谁在打。
iotop -o
输出示例:
Total DISK READ: 0.00 B/s | Total DISK WRITE: 2.81 M/s
PID PRIO USER DISK READ DISK WRITE COMMAND
3421 be/4 mysql 0.00 B 2.81 M/s mysqld
找到 mysqld 疯狂写磁盘后,下一步进 MySQL 查慢查询日志,或检查是否配置触发大量 fsync。
完整排查流程
发现服务器慢
↓
top 看 CPU
├─ id 低、us/sy 高 → CPU 瓶颈 → 找高 CPU 进程
└─ id 高、wa 高 → IO 瓶颈 → 继续往下查
↓
iostat -x 2
├─ %util 高、await 高 → 磁盘饱和
└─ %util 低、await 高 → 磁盘请求堆积,单次延迟高
↓
iotop -o
→ 找出哪个进程在大量读写
↓
针对具体进程深查(慢查询、日志积压、大文件写入……)
wa 字段:iowait 信号
top 输出中的 wa 是 iowait:
%Cpu(s): 28.3 us, 3.1 sy, 0.0 ni, 51.2 id, 16.8 wa
wa = 16.8% → 磁盘问题,不是 CPU 问题。
磁盘空间排查:IO 排查的前置步骤
磁盘空间不够时 IO 性能也会急剧下降(机械硬盘碎片化尤其严重)。空间排查永远是 IO 排查的前置。
# 1. 看各挂载点空间使用率
df -h
# 2. 找出空间大户
du -sh /* 2>/dev/null | sort -rh | head -10
du -sh /* 统计根目录下每个子目录大小,sort -rh 降序,head -10 取最大十个。
安装命令
# Debian/Ubuntu
apt install sysstat iotop
# RHEL/CentOS
dnf install sysstat iotop
关联页面
| 页面 | 关联点 |
|---|---|
| linux-disk-inspection-tools-guide | 磁盘排查工具实战指南(iostat/smartctl/lsscsi 详解) |
| linux-disk-io-tuning | 生产级 Linux 磁盘 IO 调优(调度器/内核参数/fio 基准测试) |
| server-performance-four-dimensions | 服务器性能五维排查(CPU/内存/磁盘/网络/文件系统) |
| linux-load-average-guide | Linux Load Average 详解(含 wa 字段深度解析) |
| linux-disk-space-troubleshooting | Linux 磁盘空间排查(8 命令/四种场景) |
| server-suddenly-slow-troubleshooting-sop | 服务器突然卡顿完整排查 SOP |
| linux-disk-io-monitoring-reference | 磁盘 IO 监控参考 — iostat/vmstat 字段详解与五指标框架。磁盘使用率/饱和度/IO |
| linux-perf-troubleshooting-handbook | Linux 服务器性能排查实战手册 |
实用诊断脚本
#!/bin/bash
# disk-io-diag.sh — 磁盘 IO 一站式诊断脚本
# 用法:sudo bash disk-io-diag.sh [秒数,默认5]
DURATION=${1:-5}
echo "=== 磁盘空间 ==="
df -h | grep -v "tmpfs\|devtmpfs"
echo ""
echo "=== IO 状态(${DURATION}秒采样)==="
iostat -xz 1 $DURATION
echo ""
echo "=== 最活跃的 IO 进程(Top 10)==="
pidstat -d 1 3 2>/dev/null | tail -n +4 | head -10
echo ""
echo "=== iowait 检查 ==="
top -bn1 | head -4 | grep -i "cpu\|wa"
echo ""
echo "=== 磁盘健康(S.M.A.R.T. 状态)==="
for disk in /dev/sd[a-z] /dev/nvme[0-9]n1; do
if [ -b "$disk" ]; then
smartctl -H "$disk" 2>/dev/null | grep -E "PASSED|FAILED|overall"
fi
done
运行方式:
sudo bash disk-io-diag.sh 10