定位buffer busy waits根因需查P3(class#):130为数据块磁盘加载争用,220为数据块内多行并发修改,4为段头争用,17/18为UNDO争用;须结合ASH、dba_hist_seg_stat及v$active_session_history定位具体文件与块号,并区分RAC中gc buffer busy acquire。

直接看AWR里buffer busy waits的P3值(class#)
AWR报告中「Top 5 Timed Foreground Events」只显示buffer busy waits总等待时间,但不带参数。真正要定位根因,必须查dba_hist_active_sess_history或v$event_name确认它的parameter3(即class#),因为不同class#对应完全不同的争用类型:
-
class# = 130:数据块还没读进内存,多个会话抢着从磁盘加载同一块 → 关联db file sequential read高 -
class# = 220:多个会话并发修改同一数据块内不同行 → 常见于小表高频UPDATE、无主键批量操作 -
class# = 4:段头(segment header)争用,比如FREELIST管理、HWM移动频繁 → 看Segments by Buffer Busy Waits节是否集中于某张表或索引 -
class# = 17或18:UNDO段头或UNDO块争用 → 同时检查enq: US - contention和undo segment extension等待
别只盯着“等待次数”,重点比Avg Wait(ms):同样1万次等待,平均0.3ms是轻微争用,平均12ms就是严重热块。
在AWR里找“Segments by Buffer Busy Waits”节
这个节在AWR报告末尾的「Instance Activity Statistics」之后,明确列出被buffer busy waits影响最重的对象。但它只是起点——同一张表可能有多个热点块,不能直接下结论是“这张表有问题”:
- 如果看到
SEGMENT_NAME是索引名,且CLASS是220,大概率是索引叶块分裂或高并发插入导致的叶块争用 - 如果是表名+
CLASS = 4,再查该表的INITIAL_EXTENT和FREELISTS设置,小extent+单freelist在高并发INSERT下极易卡段头 - 若对象名是
UNDO$或SEG$,说明是字典基表争用,需检查是否有大量短事务+自动undo管理配置不当
注意:这个统计基于ASH采样,不是全量;若采样间隔(默认1秒)错过瞬时高峰,可能漏掉真实热点对象。
结合DBA_HIST_SEG_STAT定位具体文件与块号
AWR本身不记录file#和block#,但dba_hist_seg_stat里的logical_reads、buffer_busy_waits列能帮你缩小范围:
- 执行:
SELECT owner, object_name, subobject_name, buffer_busy_waits, logical_reads FROM dba_hist_seg_stat s JOIN dba_objects o ON s.obj# = o.object_id WHERE snap_id BETWEEN &start_snap AND &end_snap AND buffer_busy_waits > 0 ORDER BY buffer_busy_waits DESC; - 结果中
buffer_busy_waits显著高于其他对象的,再查其data_object_id,用dba_extents反推可能的file_id和block_id范围 - 更准的做法是:用
v$active_session_history查问题时段的current_file#和current_block#,但需确保_ash_sampling_frequency没被调高(默认1s)
别跳过这步——很多DBA只停在“是哪张表”,却没继续确认是不是这张表的某个特定分区、某个特定索引分支,导致优化方案打偏。
区分buffer busy waits和gc buffer busy acquire
在RAC环境里,这两个事件名字像,但机制完全不同:buffer busy waits是单实例内缓冲区争用;gc buffer busy acquire是跨实例获取远程块时的等待。混用会导致诊断方向错误:
- 单实例库出现
buffer busy waits,不用查Global Cache and Enqueue Statistics节 - RAC库看到
buffer busy waits占比高,先确认instance_number是否为1(即非RAC模式),否则可能是节点本地缓存不足,而非GC问题 - 若两个事件同时飙升,优先排查
gc current block busy和gc cr block build time,它们才是GC链路的上游瓶颈
最容易忽略的一点:buffer busy waits在RAC中可能被掩盖——当本地块不可用时,实例会转而请求远程块,此时等待记为gc buffer busy acquire,而不是本地的buffer busy waits。所以看到GC类等待高,也得回头检查本地buffer pool是否过小或db_cache_size分配不合理。











