查in_hard_parse必须加动态时间窗口和实例感知,RAC下须用gv$active_session_history并过滤in_hard_parse='Y',避免用DBA_HIST_ACTIVE_SESS_HISTORY等低精度视图。

查 in_hard_parse 必须加动态时间窗口和实例感知
ASH内存只保留约1小时,高负载下可能缩至10–20分钟。写死时间(如 '2026-10-26 14:00:00')极易因NLS、时区或采样抖动漏掉关键样本。RAC环境下,硬解析争用常集中在某一个节点,只查 v$active_session_history 会直接丢失根因。
正确做法是:
- 用
SAMPLE_TIME > SYSDATE - INTERVAL '1' MINUTE(19c/12c)或SAMPLE_TIME > SYSDATE - INTERVAL '5' MINUTE(11g),避免SYSDATE - 1/24这类浮点运算导致范围漂移 - RAC必须用
gv$active_session_history,且建议显式加WHERE inst_id =或聚合时保留inst_id字段 - 过滤条件必须包含
in_hard_parse = 'Y',不能只靠event = 'latch: shared pool'间接推断——后者可能混入其他闩锁事件
in_hard_parse = 'Y' 的真实含义与常见误判
in_hard_parse = 'Y' 表示该采样点上会话正卡在硬解析流程中(比如语法检查、语义分析、生成执行计划),不是“刚完成硬解析”,也不是“正在软解析”。它反映的是解析过程的阻塞态,而非结果态。
容易踩的坑:
- 看到
in_hard_parse = 'Y'就去查v$sql中parse_calls高的 SQL —— 错。此时 SQL 可能还没进共享池,v$sql查不到;应优先查gv$active_session_history中的sql_id和sql_opname - 把
in_parse = 'Y'和in_hard_parse = 'Y'混为一谈。前者包括软解析,后者才是硬解析瓶颈的精确信号 - 忽略
session_state:若session_state = 'WAITING'且event是'library cache lock',说明硬解析被阻塞,真正问题在持锁者,不是当前会话写的SQL本身
定位硬解析源头:别只盯 sql_text,先看绑定变量缺失信号
硬解析爆发几乎总是由未绑定变量引起。ASH本身不存完整SQL文本,但可通过组合字段快速识别高风险模式:
- 查出高频
sql_id后,立刻关联v$sql看executions = 1但loads > 5—— 表明同一逻辑SQL反复硬解析入库 - 检查
v$sql中UNBOUND_CURSOR = 'Y',这是Oracle内部标记“未绑定变量”的明确标识 -
sql_text里含连续单引号(如... WHERE name = 'abc''def')或拼接数字(如... WHERE id = 12345)是典型硬编码特征,比看SQL文本内容更可靠 - 别用
GROUP BY sql_text聚合——不同字面量会生成几十个sql_id,掩盖共性问题
为什么 DBA_HIST_ACTIVE_SESS_HISTORY 在硬解析诊断中基本没用
AWR快照默认每小时采集一次,采样间隔长达30–60分钟,而硬解析风暴往往持续几十秒到几分钟。等你导出 DBA_HIST_ACTIVE_SESS_HISTORY 报告时,内存中的ASH样本早已被覆盖,AWR里只留下零星、稀疏、聚合后的痕迹。
典型表现:
-
DBA_HIST_ACTIVE_SESS_HISTORY中in_hard_parse = 'Y'记录极少甚至为0,但实时gv$active_session_history里每秒都有数十行 - 即使查到,
sample_time字段是四舍五入到分钟级的时间戳,无法还原精确发生时刻 - 缺少
blocking_session和blocking_instance字段,无法追踪RAC下跨节点的解析阻塞链
真要回溯,唯一可行路径是:立刻用 gv$active_session_history 定位到 sql_id 和节点 → 登录对应实例查 v$sql 和 v$session 当前状态 → 若SQL已老化,再用 dba_hist_sqltext 拼凑文本,但必须接受前1000字符可能被截断。











