free buffer waits高但DBWR CPU低说明DBWR被卡在I/O路径上:存储响应慢、异步I/O未启用或DBWR配置不足;需查v$sysstat每秒等待、db file parallel write平均等待、iostat及fast_start_mttr_target。
查 DBWR 是否卡在 I/O 路径上
free buffer waits 高但 dbwr cpu 占用低,基本说明 dbwr 不是“不动”,而是“动不了”——写请求发出去后迟迟没收到完成通知。这时候不能只盯着 v$sysstat 里的总量,得看它每秒被卡住的时长是否持续超标。
实操建议:
- 用
SELECT name, value FROM v$sysstat WHERE name = 'free buffer waits'算出最近 60 秒增量,再除以 60:若 > 100 ms/second,就是明确信号 - 查
v$session_event中 DBWR 进程(program含ora_dbw)的等待:重点看event = 'db file parallel write'的平均等待时间,若 > 15ms 且占比高,I/O 子系统已拖垮 DBWR - 别忽略
io_wait_time和write_time在v$bgprocess或 AWR “Background Wait Events” 中的分布,二者差值大,说明 OS 层或存储响应延迟严重
定位 LGWR 写盘慢还是被阻塞
log file sync 等待长,第一反应不是 LGWR 慢,而是它是否被别的进程拦住了。直接比对 log file sync 和 log file parallel write 的平均等待时间:如果两者接近(比如都在 12ms 左右),那 LGWR 就是真写不动;如果 log file sync 是 25ms 而 log file parallel write 只有 8ms,说明 LGWR 发完写就去干别的了,但前台在等它“确认提交”,问题出在日志切换、归档阻塞或 latch 争用上。
实操建议:
- 运行:
SELECT wait_time_milli, wait_count FROM v$event_histogram WHERE event = 'log file parallel write' AND wait_time_milli IN (1,2,4,8,16,32),若 16ms+ 档位占总写次数 >30%,LGWR 写盘层已饱和 - 查 ASH 中 LGWR 自身的等待:
SELECT event, p1text, p2text, COUNT(*) FROM v$active_session_history WHERE session_type = 'BACKGROUND' AND program LIKE '%LGWR%' AND sample_time > SYSDATE - 1/1440 GROUP BY event, p1text, p2text,若高频出现log file switch (checkpoint incomplete)或enq: CF - contention,就是被 checkpoint 或归档拖住 - 检查归档路径是否挂载异常、磁盘满或 NFS 延迟高,LGWR 会同步等归档完成才能重用日志组
ASH 中区分 DBWR/LGWR 真实瓶颈与假象
ASH 默认不保留后台进程采样,必须显式过滤。很多 DBA 直接查 v$active_session_history 全表,结果发现 DBWR/LGWR 几乎不出现——不是它们没事干,而是默认采样逻辑偏向前台会话。要看到它们,得强制指定 session_type = 'BACKGROUND' 并限定时间窗,否则全是噪音。
实操建议:
- 查 DBWR 等待分布(过去 2 分钟):
SELECT event, COUNT(*) c FROM v$active_session_history WHERE session_type = 'BACKGROUND' AND program LIKE '%DBW%' AND sample_time > SYSDATE - 2/1440 GROUP BY event ORDER BY c DESC - 查 LGWR 是否在等日志切换:
SELECT p1text, p1, COUNT(*) FROM v$active_session_history WHERE session_type = 'BACKGROUND' AND program LIKE '%LGWR%' AND event = 'log file switch completion' AND sample_time > SYSDATE - 1/1440 GROUP BY p1text, p1,若p1 = 0表示等 checkpoint,p1 = 1表示等归档 - 注意
v$active_session_history只保留约 1 小时数据(Oracle 默认),超时自动滚动丢弃,别查太老的时间段
避免误判:DBWR/LGWR 等待和前台等待的耦合陷阱
DBWR 写慢会引发前台的 free buffer waits,LGWR 写慢会放大前台的 log file sync,但反过来,前台 SQL 的异常行为也会反向拖垮后台进程。比如大批未提交事务持续修改热点块,会导致 DBWR 刷脏压力陡增;又比如某条 SQL 触发大量一致性读(CR),迫使 LGWR 频繁 flush redo 来构造 CR block,间接抬高 log file sync。
实操建议:
- 不要孤立看后台进程等待。当发现 DBWR 高频等
db file parallel write,顺手查同一时段前台 top SQL:SELECT sql_id, executions, buffer_gets, disk_reads FROM v$sql WHERE last_active_time > SYSDATE - 1/1440 ORDER BY disk_reads DESC,看是否有异常物理读 SQL - 当 LGWR 出现大量
gc cr block flush time相关等待,立刻关联查 RAC 中的gv$bh:SELECT file#, dbablk, class#, state FROM gv$bh WHERE state = 'xcur' AND dirty = 'Y' ORDER BY blocks DESC,确认是不是某些 block 成为全局热点 - ASH 里
blocking_session对后台进程意义有限,但current_obj#和sql_id若频繁指向同一对象或语句,就是前台驱动的后台压力源
真实瓶颈常藏在“后台等前台”或“前台等后台”的循环里。DBWR/LGWR 的等待统计只是表象,关键得用 ASH 把它们和前台活动在时间轴上对齐——哪怕只差 3 秒,也可能漏掉那个触发连锁反应的 SQL。











