<p>直接查v$active_session_history的in_hard_parse列可快速定位尚未生成sql_id的“幽灵SQL”,因其在硬解析阶段即被每秒采样标记为'Y',早于v$sql记录;必须加sample_time > SYSDATE - 1/144过滤并按session_id等分组聚合,结合event、program等字段溯源。</p>

直接查 v$active_session_history 的 in_hard_parse 列,比翻 AWR 或扫 v$sql 更快定位尚未进入共享池的“幽灵 SQL”——这类 SQL 甚至没来得及生成 sql_id,但已在 ASH 中留下硬解析痕迹。
为什么 in_hard_parse = 'Y' 比 parse count (hard) 更早暴露问题
硬解析完成前,SQL 还没被赋予 sql_id,也不会写入 v$sql;但 ASH 每秒采样一次会话状态,只要该会话正卡在硬解析阶段,in_hard_parse 就是 'Y'。这能捕获三类关键场景:
- 语法错误或权限缺失导致反复解析失败(如警告日志里的
WARNING: too many parse errors) - 应用用拼接字符串方式执行 SQL,每次字面量不同,根本不会复用游标
- 存储过程里
EXECUTE IMMEDIATE调用未绑定变量语句,且执行频率极高
此时 v$sql 里可能只有零星几条 EXECUTIONS = 1 的记录,而 ASH 已显示持续数分钟的 in_hard_parse = 'Y' 占比超 80%。
查 in_hard_parse 必须加时间过滤和聚合
不加约束的全表扫 v$active_session_history 效率极低,且结果稀释。关键操作有:
- 必须限定
sample_time > SYSDATE - 1/144(最近 10 分钟),ASH 内存缓冲区高负载下仅保留约 30–60 分钟数据 - 按
session_id,session_serial#,sql_id(若有)分组统计,避免把同一会话的连续硬解析记为多条独立事件 - 优先看
in_hard_parse = 'Y'且in_parse = 'Y'同时为真的行——排除软解析干扰
示例查询:
SELECT session_id, session_serial#, sql_id, COUNT(*) samples FROM v$active_session_history WHERE in_hard_parse = 'Y' AND in_parse = 'Y' AND sample_time > SYSDATE - 1/144 GROUP BY session_id, session_serial#, sql_id ORDER BY samples DESC FETCH FIRST 5 ROWS ONLY;
拿到可疑会话后,怎么捞出真实 SQL 文本
多数情况下,sql_id 是空或为 0000000000000000,这时不能依赖 v$sqltext。可靠路径是:
- 用
session_id和session_serial#查v$session,重点关注sql_hash_value、prev_sql_id、program和machine字段,缩小应用来源范围 - 若
event列显示cursor: pin S wait on X或library cache lock,基本可断定是硬解析争用,不是 SQL 执行本身慢 - 对长期
STATE = 'ON CPU'且IN_HARD_PARSE = 'Y'的会话,用oradebug dump errorstack 3抓堆栈,里面常含未格式化的原始 SQL 片段
注意:DBMS_XPLAN.DISPLAY_CURSOR 对这类 SQL 无效——它还没生成可查的游标。
容易忽略的两个信号:PGA memory operation 和 ON CPU 长期并存
当大量会话卡在硬解析时,v$session 常见现象是 event = 'PGA memory operation' + state = 'ON CPU' + last_call_et 持续增长。这不是内存不足,而是解析器在反复分配/释放 PGA 中的语法树内存。此时:
- 别急着调大
pga_aggregate_target,先确认是否由未绑定变量触发 - 检查
v$sgastat中free memory是否低于 20MB,过小的 shared pool 会让新解析对象无法驻留,加剧反复硬解析 - 若
v$sql_shared_cursor显示大量OPTIMIZER_MISMATCH = 'Y',要查是否有人在会话级执行了ALTER SESSION SET optimizer_features_enable
真正难处理的,是那些连 sql_text 都没机会落库、只在 ASH 里一闪而过的解析风暴——它们往往来自 JDBC 驱动自动重试、ORM 框架的动态 SQL 生成,或监控脚本的非法查询。


















