# Linux CPU 输出诊断分析(iowait 场景)
## 原始输出
```
%Cpu(s): 2.1 us, 0.7 sy, 0.0 ni, 32.0 id, 65.0 wa, 0.1 hi, 0.0 si, 0.0 st
```
## 一句话定性
**不是 CPU 忙,是磁盘 I/O 把 CPU 等闲了** —— 典型的 **I/O 瓶颈(iowait 主导)**,CPU 本身非常空闲。
## 逐项拆解
| 指标 | 值 | 含义 |
|---|---|---|
| `us` | 2.1% | 用户态(业务进程,含 Oracle server process)计算极少 |
| `sy` | 0.7% | 内核态开销极低 |
| `ni` | 0.0% | nice 调整过的进程占比,忽略 |
| `id` | 32.0% | 真正空闲的 CPU 只有 1/3 |
| **`wa`** | **65.0%** | **65% 的 CPU 时间在等磁盘返回** |
| `hi` | 0.1% | 硬中断,可忽略 |
| `si` | 0.0% | 软中断,可忽略 |
| `st` | 0.0% | 虚拟化偷取,可忽略 |
**关键点**:`id + wa = 97%`,说明机器上几乎没有真正在跑计算的活儿,CPU 大多时间 block 在 `wait_on_buffer` / `io_schedule` 上。如果是 CPU 瓶颈,应该看到 `us+sy` 上去而 `id` 很低——现在完全相反。
## 在 EBS / Oracle 场景下的常见根因(按概率)
1. **全表扫描 / 低效 SQL 被放到磁盘排序**——大结果集走 `direct path read`、`db file scattered read`,把物理读打满。
2. **日志写突增**——`redo log` 太小导致 log switch 频繁、归档(archivelog)跟不上,LGWR/ARCn 把磁盘写满。
3. **校验点 / 增量检查点**触发,DBWn 集中刷脏块。
4. **存储层本身慢**——NFS/网存抖动、RAID 卡缓存被关、HDD 换成慢盘、某个数据文件所在 LUN 被其他租户挤占。
5. **大事务批量 DML**(如 EBS 接口表批量导入、并发请求)产生大量 undo/redo。
6. **内存压力导致换页**——但现在 `si` 是 0,基本可排除 swap。
## 下一步排查命令(按顺序)
### OS 层先定位是哪块盘在堵
```bash
iostat -xz 1 5 # 看 %util、await、svctm,定位设备
vmstat 1 5 # 看 b 列(blocked 进程数)、wa
iotop -boP # 直接看哪个进程在刷盘(Oracle spid)
```
### Oracle 层把 OS 进程映射回 SQL
```sql
-- 当前 TOP 等待事件
SELECT event, total_waits, time_waited/1000 sec, average_wait/100 ms
FROM v$system_event
WHERE wait_class = 'User I/O'
ORDER BY time_waited DESC;
-- 正在等 I/O 的会话在跑什么 SQL
SELECT s.sid, s.event, p.spid, q.sql_text
FROM v$session s, v$process p, v$sql q
WHERE s.paddr = p.addr
AND s.sql_address = q.address
AND s.event LIKE '%file%';
```
### 对照判断方向
| 观察到的等待事件 | 方向 |
|---|---|
| `db file sequential read / scattered read` 高 | SQL 问题,抓 top SQL 看执行计划 |
| `log file sync / log file parallel write` 高 | LGWR/redo 问题,查 redo size 和磁盘写延迟 |
| `free buffer waits / write complete waits` 高 | DBWn 刷不动,检查 DB_WRITER_PROCESSES 和磁盘带宽 |
| iostat 显示单盘 `%util≈100%` 而 await 飙到几十 ms | 存储/盘的物理问题,不是 Oracle 能调的 |
Linux CPU 输出诊断分析(iowait 场景)
未经允许不得转载:徐万新之路 » Linux CPU 输出诊断分析(iowait 场景)

徐万新之路

