awr中latch: cache buffers chains占比高说明存在热点块争用,表现为多会话高频争抢同一buffer chain的latch,典型场景为序列主键插入或频繁更新配置表首行,需结合pct get miss>0.5%、avg slps/miss>2等指标确认。
awr里看到latch: cache buffers chains占比高,说明什么
这代表多个会话在高频争抢同一个buffer chain上的latch,不是锁表或行锁问题,而是底层buffer header链表访问冲突。常见于热点块(比如序列主键插入末尾页、频繁更新的配置表首行)被反复pin/unpin。
关键判断依据:latch: cache buffers chains在Top 5 Timed Events中占比超过10%,且Pct Get Miss > 0.5%、Avg Slps/Miss > 2,基本可确认是热点块争用。
- 查热点对象:用
SELECT owner, object_name FROM dba_objects WHERE data_object_id IN (SELECT p1 FROM v$session_wait WHERE event = 'latch: cache buffers chains' AND rownum - 查SQL特征:结合ASH,过滤
event = 'latch: cache buffers chains'的会话,看它们共同执行的sql_id是否集中在某条update或select语句 - 注意区分:如果
sql_id不同但p2(buffer#)高度重复,说明是物理块热;如果p2分散但p1(latch addr)集中,则是latch本身热(比如单个chain过长)
mutex sleep和latch wait混在一起,怎么分清主次
AWR里latch和mutex等待事件必须分开看——它们机制不同、诊断路径也不同。mutex是更细粒度的轻量级同步机制(如cursor pin、library cache),而latch保护的是SGA中更大范围的结构(如buffer chain、shared pool)。
实际排查时优先级是:先看mutex: cursor pin s或library cache mutex是否排进Top 5。如果它和latch: cache buffers chains同时高,大概率是硬解析引发的连锁反应:硬解析→library cache争用→大量child cursor生成→buffer访问放大→chain latch争用。
- 验证硬解析:查
gv$sql中loads > 50且executions 的SQL,尤其关注<code>parsing_schema_name是否为应用用户而非SYS - 查mutex持有者:用
SELECT * FROM gv$mutex_sleep_history WHERE sleeps > 100 ORDER BY sleeps DESC,重点关注location字段值如"cursor pin" - 不要只盯着wait time总和:一个
mutex: library cache平均等待2ms但发生10万次,比一个latch: gc buffer busy acquire等3秒但只发生5次影响更广
gc buffer busy acquire和latch竞争能同时存在吗
能,而且很常见——RAC环境下这两类等待经常耦合出现。根本原因是:远程实例发来的CR块请求,在本地实例上要先获取对应buffer的cache buffers chains latch才能pin住,如果此时本地已有会话正持有该latch修改同一块,就会先触发latch: cache buffers chains等待,再叠加gc buffer busy acquire。
典型链路:INSERT INTO t(id) VALUES(seq.nextval) → 主键索引叶块分裂 → 本地会话持latch写块 → 远程实例请求该块CR镜像 → 等待gc buffer busy acquire → 但本地latch未释放 → 远程会话实际卡在latch层
- 看AWR里两个事件是否同时间段飙升:用
SELECT snap_id, event, time_waited_micro/1000000 wait_sec FROM dba_hist_system_event WHERE event IN ('gc buffer busy acquire', 'latch: cache buffers chains') AND snap_id BETWEEN &begin AND &end ORDER BY snap_id - 查争用块归属:从
gv$session_wait取p1(class#)、p2(file#)、p3(block#),用SELECT owner, segment_name FROM dba_extents WHERE file_id = &p2 AND &p3 BETWEEN block_id AND block_id + blocks - 1 - 别误判为纯RAC问题:即使关掉RAC,单实例下
latch: cache buffers chains照样会因热点块爆发——RAC只是把争用从“本机多会话”放大成“跨实例+本机会话”双重压力
为什么调大_shared_pool_size反而让mutex争用更严重
Shared Pool扩容不解决mutex争用,反而可能加剧——因为mutex是按bucket哈希分布的,pool变大后bucket数量未必同比增加,导致每个bucket管理的chunk更多,单个mutex保护范围扩大,争用面反而更集中。
真正有效的动作不是堆内存,而是减少共享池内需保护的对象数量:比如绑定变量缺失导致大量相似SQL硬解析,每条都生成独立cursor,每个cursor都要竞争library cache mutex。
- 检查
library cache相关latch/mutex:对比gv$latch中library cache类latch的Get Requests和Misses,若Misses占比突增,说明解析压力已超临界点 - 临时缓解:设置
_kghdsidx_count=16(默认8)可增加library cache hash bucket数,但需重启实例 - 根治方法:应用层强制使用绑定变量,DB层禁用
cursor_sharing=force(它会产生不可控的child cursor爆炸)
真实环境里最易被忽略的点:latch: cache buffers chains等待背后,90%以上不是SQL写得差,而是数据模型或访问模式没适配RAC特性——比如用sequence做主键+高并发insert,本质就是在制造人为热点。这类问题调参数、加硬件都没用,必须改设计。











