查 latch: shared pool 的活跃 sql 必须加时间窗口和事件过滤,即 where event = 'latch: shared pool' 且 sample_time > sysdate - interval '1' minute,rac 下用 gv$ash,按 sql_id 和 sql_opname 聚合,避免 group by sql_text,并结合 v$sql 中 sql_text 含连续单引号、executions=1但loads>5、unbound_cursor='y' 等信号确认未绑定变量。

查 latch: shared pool 的活跃 SQL 必须加时间窗口和事件过滤
ASH 里不加 WHERE event = 'latch: shared pool' 就去查 SQL,等于在一堆等待中找 CPU 争用,结果全是噪音。这个事件明确指向硬解析引发的共享池闩锁争抢,不是配置小、也不是 latch_count 不够——是 SQL 没绑定变量,反复进 pool 导致链表过长、争抢加剧。
必须同时满足两个条件才有效:
– event = 'latch: shared pool'(大小写敏感,不能写成 'LATCH: SHARED POOL' 或小写)
– SAMPLE_TIME > SYSDATE - INTERVAL '1' MINUTE(19c/12c 推荐用 1 分钟;11g 可放宽到 5 分钟,但别用 SYSDATE - 1/24,NLS 设置可能让范围漂移)
RAC 环境下必须用 gv$active_session_history,否则只看到当前节点样本,而争用可能集中在 node3 上。
聚合时按 sql_id 和 sql_opname 分组,别漏掉 DML
很多 DBA 只查 SELECT,但 INSERT/UPDATE/DELETE 同样会硬解析,尤其带子查询或触发器的 DML,解析开销更大。用 sql_opname 能一眼区分操作类型,避免把高频 UPDATE 当成“无关语句”忽略。
示例语句直接可用:
SELECT sql_id, sql_opname, COUNT(*) cnt FROM gv$active_session_history WHERE event = 'latch: shared pool' AND sample_time > SYSDATE - INTERVAL '1' MINUTE GROUP BY sql_id, sql_opname ORDER BY cnt DESC FETCH FIRST 10 ROWS ONLY;
注意:
– 不要 GROUP BY sql_text,绑定变量缺失会导致同一逻辑 SQL 出现几十个不同 sql_id
– 别用 DBA_HIST_ACTIVE_SESS_HISTORY 替代,那是 AWR 快照,延迟高、采样稀疏,抓不到瞬时争用
验证 SQL 是否真没绑定变量,看三处关键信号
拿到 top sql_id 后,不能只看执行次数。真正能坐实“每次换值都重编译”的证据在 v$sql 里有三处:
-
sql_text LIKE '%''%''%':连续两个单引号代表字符串字面量(如WHERE name = 'JOHN'),这是最直观信号 -
executions = 1但loads > 5:说明它被硬解析了多次,但几乎没重用过 -
UNBOUND_CURSOR = 'Y'(查v$sql_shared_cursor):Oracle 明确标记“无法复用游标”,比人工判断更权威
如果 v$sql 里查不到文本,别急着翻 AWR,先查 dba_hist_sqltext;若仍为空,大概率是该 SQL 根本没缓存成功(被 ORA-04031 踢出),这时 ASH 记录反而是唯一证据。
别忽略 in_hard_parse = 'Y' 这个直接指标
v$active_session_history 里有两列专为解析诊断设计:in_parse 和 in_hard_parse。比起靠 event 间接推断,直接查 in_hard_parse = 'Y' 更干净——它表示采样那一刻,会话正卡在硬解析栈帧里。
快速确认是否解析主导问题:
SELECT in_parse, in_hard_parse, COUNT(*) cnt FROM gv$active_session_history WHERE sample_time > SYSDATE - INTERVAL '1' MINUTE GROUP BY in_parse, in_hard_parse ORDER BY cnt DESC;
若输出中 in_hard_parse = 'Y' 占比超 80%,基本不用再往下查,就是硬解析风暴。这时候调大 shared_pool_size 或 flush pool,只会让问题更糟。
真实场景里,in_hard_parse 是比 event 更早、更细粒度的信号——有些硬解析还没走到 latch 争抢那步就卡在词法分析或权限检查了,这时 event 可能还是空,但 in_hard_parse 已经是 Y。











