磁盘I/O高问题定位

一、先快速判断:是不是 I/O 高?

bash

top

看这一行:

%Cpu(s):  5.2 us,  2.3 sy,  0.0 ni, 82.5 id, **10.0 wa**

只要满足:

  • wa(iowait) ≥ 10% → 已经是 I/O 高
  • wa ≥ 20% → 严重 I/O 瓶颈,系统会很卡
  • wa ≥ 30% → 基本卡死

只要 wa 高,CPU 再闲也没用,系统就是慢

二、第一步:看谁在疯狂读写(最关键)

bash

iotop

快捷键:

  • o:只看正在读写的进程
  • P:按读写字节排序

你会立刻看到:

  • 哪个 PID
  • 哪个程序(mysqld、java、rsync、tar、gzip 等)
  • 读速度、写速度

90% 的问题,这一步直接定位。

三、第二步:看哪个磁盘在忙

bash

iostat -x 1 2

重点看:

  • util:磁盘繁忙度
    • util ≥ 70% → 很忙
    • util ≥ 100% → 跑满
  • rMB/s、wMB/s:真实读写速度
  • await:I/O 响应时间
    • await < 10ms:正常
    • await > 50ms:很慢
    • await > 100ms:磁盘快挂了 / 被打满

四、第三步:看哪个文件在被疯狂读写

bash

lsof -p 进程PID

或者用:

bash

ls -lh /proc/进程PID/fd

能看到:

  • 日志文件
  • 数据文件
  • 临时文件

五、第四步:看哪个目录 / 文件最大

bash

# 看根目录下谁最大
du -sh /* | sort -rh | head -10

# 看某个目录
du -sh /data/* | sort -rh | head -10

常见凶手:

  • 超大日志
  • 慢查询日志
  • 大量小文件读写
  • 数据库刷盘

六、线上 I/O 高 常见真凶(你对照看)

  1. MySQL 疯狂写
    • 大量插入 / 更新
    • 没有索引,全表扫描
    • 刷 binlog/redo 日志
  2. 日志疯狂输出
    • 程序疯狂打日志(ERROR 死循环打印)
    • 日志没切割,文件巨大
  3. 定时任务在跑
    • find、tar、gzip、rsync、备份
    • 白天跑,直接打满磁盘
  4. SWAP 被使用
    • 内存不够,用 swap = 超级慢
    bash运行free -h
  5. 磁盘本身故障
    • util 100%,但没有进程读写
    • await 特别高→ 硬盘快坏了

七、最简单万能排查流程(背这个)

  1. top 看 wa 高不高
  2. iotop 找耗 I/O 的进程
  3. iostat -x 看哪块盘忙
  4. lsof 看读写哪个文件
  5. du 看哪个目录大
  6. 处理:停进程 / 切日志 / 加索引 / 换盘

八、你可以直接用的一句话命令

bash

# 实时看I/O
iotop

# 看磁盘繁忙度
iostat -x 1

# 看最占空间的目录
du -sh /* | sort -rh | head 10

# 看某个进程在读写什么
lsof -p PID
滚动至顶部