latch: cache buffers chains是热点块或低效sql引发的cbc闩锁争用症状,需先验证其占db time是否超5%且平均等待是否>100μs;若不满足,则非根因,应优先排查高逻辑读sql、热点块及buffer busy waits等关联事件。

先确认是不是真瓶颈,别被P1RAW地址带偏
看到 latch: cache buffers chains 在 Top 5 等待事件里排前几,不代表它就是根因——它只是症状。真正要盯的是:这个等待的总时间是否占 DB Time 超过 5%,且平均等待时间是否持续 >100 µs。如果平均等待才 12 µs,哪怕频次高,也大概率是正常并发下的自旋开销,不是 latch 持有时间长导致的阻塞。此时翻 v$session_wait 查 P1RAW 地址没意义,因为大量会话在不同子 latch 上短暂争用,地址根本聚不起来。
实操建议:
- 先看 AWR 报告头部的「DB Time(s)」和「DB CPU(s)」,算出
latch: cache buffers chains等待总秒数占 DB Time 的比例; - 再查该事件的「Avg Wait(ms)」列,低于 0.1 ms 基本可排除严重 latch 持有问题;
- 如果占比高 + 平均等待长(比如 >0.5 ms),再往下挖;否则优先看 SQL Statistics 或 log file sync。
从SQL Statistics反向定位高逻辑读SQL
latch: cache buffers chains 争用几乎总是由高 BUFFER_GETS 的 SQL 引发——每次逻辑读都要获取一次 CBC latch,所以 BUFFER_GETS/EXECUTIONS 高的语句才是元凶,不是执行时间长的那几个。
实操建议:
- 跳转到 AWR 报告的「SQL ordered by Buffer Gets」部分,排序按「Buffer Gets」降序;
- 重点筛出
Buffer Gets Per Exec> 10,000 且Executions> 50 的 SQL; - 忽略那些
Buffer Gets高但Executions只有 1–2 次的“一次性大扫”,它们不造成持续争用; - 对命中 SQL,立刻查
v$sql_plan,看是否有全表扫描、嵌套循环驱动大结果集、或索引回表次数爆炸(如 NL join on index range scan 返回 10 万行)。
用ASH交叉验证热点块对象,别只信CURRENT_OBJ#
v$active_session_history 里的 CURRENT_OBJ# 字段经常为空或不准,尤其当争用发生在索引叶块、根块或 undo header 块时——这些块不属于任何用户对象。直接 JOIN dba_objects 会漏掉关键线索。
实操建议:
- 运行:
SELECT COUNT(*), CURRENT_FILE#, CURRENT_BLOCK#, CURRENT_OBJ#, SQL_ID FROM v$active_session_history WHERE event = 'latch: cache buffers chains' AND sample_time > SYSDATE - 1/24 GROUP BY CURRENT_FILE#, CURRENT_BLOCK#, CURRENT_OBJ#, SQL_ID ORDER BY COUNT(*) DESC FETCH FIRST 5 ROWS ONLY; - 拿到高频
CURRENT_FILE#和CURRENT_BLOCK#后,用DBMS_UTILITY.DATA_BLOCK_ADDRESS_FILE和DATA_BLOCK_ADDRESS_BLOCK解析真实文件/块号; - 再查
SELECT segment_name, segment_type FROM dba_extents WHERE file_id = :f AND :b BETWEEN block_id AND block_id + blocks - 1,定位物理段; - 特别注意:若块落在
file# = 2(system 表空间)或file# = 1(undo 表空间),说明是数据字典热块或事务热点,不是业务表问题。
调优后必须验证 latch 获取频次是否下降
改完 SQL 或加了索引,AWR 里 latch: cache buffers chains 的等待秒数可能还没明显变,但更关键的指标是 latch 获取总数是否下来了——这反映底层内存访问模式是否真的改善。
实操建议:
- 对比优化前后两个 AWR 报告,在「Instance Activity Stats」部分找
consistent gets和db block gets是否同步下降; - 同时查
v$latch视图:SELECT name, gets, misses, spin_gets FROM v$latch WHERE name = 'cache buffers chains';
—— 如果misses / gets从 5% 降到 0.3%,说明争用本质缓解; - 警惕「等待时间降了但 miss 比例没动」:可能是应用减少了并发,而非 SQL 更高效。
最易被忽略的一点:CBC latch 争用常伴随 buffer busy waits 或 read by other session 同时升高,这三个事件要一起看。单独调一条 SQL 可能治标不治本——如果底层是单块索引主键更新(如订单号序列),再好的执行计划也压不住 latch 争用,这时候得考虑应用层拆分或 hash 分区。











