服务器 IO 过高排查流程
1. 看 %iowait 列,值高代表大量进程在等磁盘 IO
---
## 2. 定位高 IO 进程
### 1. 实时查看进程 IO(首选)
2. 按 IO 排序,每秒刷新
iotop -oP 1
- `DISK READ` / `DISK WRITE`:直接看到进程实时读写速度
- 找到流量大、持续占用的 PID、进程名
### 2. pidstat 简洁版
pidstat -d 1
3. 查看每个进程的磁盘读写、IO 等待
---
## 3. 定位进程读写文件
拿到高 IO PID(假设为 1234):
### 1. 查看进程打开的文件
lsof -p 1234
### 2. 跟踪进程实时读写
4. 跟踪该 PID 的系统调用,重点看 read/write
strace -p 1234 -e trace=file,read,write
### 3. 查看目录整体读写
5. 统计目录文件大小、增量,排查日志刷屏、大文件拷贝
du -sh /xxx/path
6. 观察文件增长
watch -n1 ls -lh /xxx/path
---
## 4. 区分 IO 类型判断根因
### 场景 1:大量写 IO(最常见)
**典型现象**:`wMB/s` 高、`%util` 满
**常见原因**:
- 日志狂打:应用日志、Nginx/Tomcat/数据库日志不停刷盘
- 数据库:MySQL 慢查询、大批量 INSERT/UPDATE、事务日志刷盘
- 定时任务:备份、同步、文件拷贝、解压压缩
- 应用:本地临时文件、缓存文件频繁写入
### 场景 2:大量读 IO
**典型现象**:`rMB/s` 高
**常见原因**:
- 数据库:全表扫描、索引失效、大量查询热点数据
- 程序批量读取大文件、离线分析、日志采集
- 缓存失效,大量请求直读磁盘
### 场景 3:随机 IO 高(数据库典型)
**现象**:`await` 很高、吞吐不大,但磁盘跑满
- MySQL/PostgreSQL 索引差、行锁、频繁小事务、分页查询烂
### 场景 4:磁盘硬件问题
- 单块机械盘(HDD)性能弱,并发 IO 直接打满
- 磁盘故障、RAID 降级、缓存策略异常
- 分区/挂载点不合理,热点集中单块盘
---
## 5. 数据库专项排查(IO 高高发区)
以 MySQL 为例:
### 1. 查看慢查询
show variables like ‘slow_query%‘;
7. 分析慢日志
mysqldumpslow -s t /var/log/mysql/slow.log
### 2. 查看当前会话 IO、事务
show processlist;
show engine innodb status\G
### 3. 检查刷盘策略
`innodb_flush_log_at_trx_commit`、`sync_binlog` 配置过严会拉高写 IO。
---
## 6. 快速临时缓解 + 根治方案
### 临时应急
1. 暂停/杀掉异常高 IO 进程、定时任务
2. 临时滚动清空暴涨日志(先备份)
3. 数据库先 kill 掉耗时大查询
### 根治方向
| 方向 | 措施 |
|------|------|
| **日志** | 分级日志、轮转切割、关闭冗余 DEBUG 日志、远端日志收集 |
| **数据库** | 加索引、优化 SQL、分库分表、调整刷盘参数、升级 SSD |
| **应用** | 加本地缓存/Redis,减少磁盘直接读写 |
| **架构** | 冷热数据分离、大文件异步处理、避免同步大 IO 操作 |
---
## 7. 排查命令速记(一条流)
8. 看整机 IO
iostat -xd 1
9. 抓高 IO 进程
iotop -o 1
10. 查进程打开文件
lsof -p PID
11. 跟踪读写行为
strace -p PID
12. 看系统负载 + iowait
top
---
> [!info] 关联文档
> - [[iostat 命令详解]]:IO 查看工具详解
> - [[Linux]]:Linux 系统管理主页
> - [[监控与可观测性]]:系统监控体系
> - [[eBPF 技术详解]]:内核级 IO 追踪
