buffer busy waits 高频出现表明存在热块或资源瓶颈,需通过p1(file#)、p2(block#)、p3(class#)定位具体块和对象;awr不直接提供,须查v$session_wait_history或ash。

buffer busy waits 高频出现,说明不是偶发争用,而是存在明确的热块或资源瓶颈,必须定位到具体块和对象才能解决。
查清等待参数:file#、block#、class# 三个值缺一不可
仅看等待次数或总时间没用,buffer busy waits 的 p1(file#)、p2(block#)、p3(class#)才是关键线索。AWR 报告里不直接展示这三个值,得从 v$session_wait_history 或 ASH 数据中提取:
- 先用
SELECT event, p1, p2, p3 FROM v$session_wait_history WHERE event = 'buffer busy waits' AND rownum 拿最近的样本 -
p1和p2联合可定位物理块:SELECT owner, segment_name, segment_type FROM dba_extents WHERE file_id = &p1 AND &p2 BETWEEN block_id AND block_id + blocks - 1 -
p3决定根因类型:比如4是数据段头争用,17或18指向 UNDO 段问题,130或220多为普通数据块热块
区分是“热数据块”还是“热段头”,处理方式完全不同
同一类等待,但背后机制差异极大,不能统一加索引或调 buffer cache:
- 若
p3 = 4(段头争用):常见于 FREELIST 管理的非 ASSM 表空间,高并发 INSERT 导致多个会话抢同一个段头块。解法是改用ASSM,或对大表预分配足够 extent,避免频繁扩展 HWM - 若
p3 = 17或18(UNDO 段头或块争用):说明 UNDO 表空间配置不足,undo_retention过小或 UNDO 表空间太小,导致一致性读反复回滚段找旧镜像。应增大undo_tablespace容量,并确认undo_retention≥ 最长查询运行时间 - 若
p3 = 130或220且定位到小表(如配置表、状态码表):极大概率是全表扫描+高并发更新造成的热块。此时加索引未必有用,反而可能让叶块变热;更有效的是把该表cache到 buffer pool,或改用/*+ FULL */提示强制走全扫但减少逻辑读竞争
验证是否真由缓存不足引发 —— 别被 buffer hit ratio 带偏
Buffer Hit Ratio 93% 看似还行,但在 OLTP 场景下已偏低;更关键的是看 free buffer waits 是否同步升高。如果两者共现,说明 buffer cache 不是不够大,而是写入跟不上:
-
free buffer waits高 → DBWR 写不过来 → 检查db_writer_processes是否过少、磁盘 I/O 是否饱和、是否有大量write complete waits - 即使
buffer busy waits单独高,也要核对physical reads和db block changes比例:若后者远高于前者,说明是 DML 密集型热块,而非读多写少 - 不要盲目加大
db_cache_size:块越多,CBC latch 争用可能越严重;优先做对象级优化(如分区、reverse key index)比堆内存更有效
最易忽略的一点:应用层批量操作没控制节奏
很多 case 其实和 SQL 或配置无关,而是开发在跑批时一次性提交几万条记录,所有事务挤在同一个块上更新(比如 status 字段),或反复扫同一张小维表。这种场景下:
- DBA 查到热块也难优化——因为块本身没问题,是业务逻辑把压力集中了
- 必须推动应用加
commit控制粒度(如每 500 行 commit 一次),或改用MERGE+APPEND减少单块修改频率 - 临时缓解可用
ALTER TABLE ... PCTFREE 90降低块内行密度,但只是掩耳盗铃,长期仍需拆分逻辑











