根因判断需先验证Avg Wait(ms)是否真超标,若≤0.5ms或DB Time占比<5%,则非根因;再聚焦高Buffer Gets/Exec的SQL,结合ASH与x$bh定位热点块,而非依赖CURRENT_OBJ#。

不是Top 5里排第一就等于它是根因——90%的误判都卡在这一步。
先看AWR里Avg Wait是否真超标
latch: cache buffers chains 在 Top Events 里靠前,只说明它“出现得多”,不等于它“拖得久”。关键看两个数字:DB Time(s) 和该事件的 Avg Wait(ms)。
- 如果
Avg Wait(ms) - 必须同时满足:
latch: cache buffers chains等待总秒数 ÷DB Time(s)> 5% 且Avg Wait(ms)> 0.5 - 不满足就别往下查
P1RAW地址——不同会话在不同子 latch 上抢,地址根本聚不起来
直接跳去SQL Statistics找高逻辑读SQL
cbc 争用几乎总是由高 Buffer Gets 的 SQL 引发,不是执行慢的 SQL,而是“每执行一次就扫几万块”的 SQL。
- 打开 AWR 报告 → 找「
SQL ordered by Buffer Gets」部分 - 重点筛:
Buffer Gets Per Exec> 10000 且Executions> 50 的语句 - 忽略那些
Buffer Gets高但Executions= 1–2 的“一次性大扫”,它们不造成持续争用 - 对命中 SQL,立刻查
v$sql_plan,盯死:全表扫描、NL join 驱动大结果集、索引回表爆炸(比如 index range scan 返回 10 万行再 NL)
用ASH查热点块时别信CURRENT_OBJ#
v$active_session_history 的 CURRENT_OBJ# 经常为空或不准,尤其当争用发生在索引叶块、根块、undo header 块时——这些块不属于任何用户对象。
- 正确做法:JOIN
x$bh+dba_extents,而不是依赖CURRENT_OBJ# - 先从
dba_hist_active_sess_history提取故障时段的P1RAW值,转成 addr 后查x$bh: SELECT file#, dbablk, tch FROM x$bh WHERE hladdr = '&P1RAW' ORDER BY tch DESC- 再用
file#和dbablk查dba_extents定位真实段,哪怕返回空也要接受——说明热点在系统块上
查v$latch_children时重点关注sleeps/misses比值
子 latch 的争用程度不能只看 gets,要盯 sleeps 和 misses 的关系。
SELECT addr, child#, gets, misses, sleeps FROM v$latch_children WHERE name = 'cache buffers chains' ORDER BY sleeps DESC- 如果某 child 的
sleeps / misses> 0.3,说明它频繁失败后被迫休眠,是真正瓶颈点 - 注意:Oracle 19c+ 默认
_db_block_hash_latches是自动计算的,手动调参风险高,优先优化 SQL 或分散访问模式
最常被跳过的动作是验证平均等待时间——很多人看到 Top 1 就开干,结果花了两小时查 P1RAW,发现平均才 12 µs,白忙。











