ash能实时捕获正在硬解析的非绑定变量sql,比v$sql更及时准确;force_matching_signature用于识别结构相同但字面量不同的语句,需与ash联动验证才能精准定位问题。
直接结论:ash(v$active_session_history)能实时抓到正在硬解析的非绑定变量 sql,比查 v$sql 更快、更准;force_matching_signature 是识别“长得像但没绑变量”的关键指纹,但它本身不触发解析,只是辅助验证。
怎么用 ASH 实时抓出正在硬解析的语句
硬解析是瞬时动作,v$sql 只记录已缓存的结果,等你去查时可能早被刷出或合并了。ASH 每秒采样一次会话状态,in_hard_parse = 'Y' 就是正在硬解析的铁证。
- 查最近 15 分钟最活跃的硬解析 SQL:
SELECT sql_id, sql_text, COUNT(*) cnt<br>FROM v$active_session_history<br>WHERE sample_time > SYSDATE - 15/1440<br> AND in_hard_parse = 'Y'<br> AND sql_id IS NOT NULL<br>GROUP BY sql_id, sql_text<br>ORDER BY cnt DESC<br>LIMIT 10;
- 注意过滤掉
sql_id IS NOT NULL,否则会混入匿名 PL/SQL 块(如declare ... execute immediate);这类语句在sql_text里往往带拼接字面量,比如'select * from t where id = '||i,一眼就能看出没绑变量 - 别依赖
v$sql.executions = 1来筛——有些语句执行了 100 次但每次都是硬解析,executions还是 100,parse_calls却也是 100,这种才最危险
FORCE_MATCHING_SIGNATURE 怎么用、为什么不能单靠它
FORCE_MATCHING_SIGNATURE 是 Oracle 对 SQL 文本做“忽略字面量”哈希后的值。两个语句仅数字/字符串不同,但结构一致,签名就相同——这是判断“本该用绑定变量却没用”的核心依据。
- 查签名重复但
sql_id不同的 top 组:SELECT force_matching_signature, COUNT(*) cnt, MIN(sql_id) example_sql_id<br>FROM v$sql<br>WHERE force_matching_signature != 0<br> AND parsing_schema_name NOT IN ('SYS','SYSTEM')<br>GROUP BY force_matching_signature<br>HAVING COUNT(*) > 5<br>ORDER BY cnt DESC<br>LIMIT 5; - 拿到
example_sql_id后,再查具体语句:SELECT sql_text, executions, parse_calls FROM v$sql WHERE sql_id = 'xxx';—— 如果executions = parse_calls,基本坐实没绑变量 - 陷阱:CURSOR_SHARING=FORCE 会强制改写,让签名相同,但执行计划可能失真;所以生产库禁用
CURSOR_SHARING=SIMILAR,也别设FORCE,它只是掩耳盗铃
ASH 和 FORCE_MATCHING_SIGNATURE 联动验证的实操路径
单独用哪个都容易误判。真实排查要闭环:ASH 定位“此刻谁在硬解析” → 查出的 sql_id 去 v$sql 看 force_matching_signature → 再反查同签名其他 sql_id,确认是否大量堆积。
- 例如 ASH 抓到
sql_id = 'abc123'高频硬解析,执行:SELECT force_matching_signature FROM v$sql WHERE sql_id = 'abc123';
得到签名1234567890 - 再查同签名有多少条:
SELECT COUNT(*) FROM v$sql WHERE force_matching_signature = 1234567890;—— 如果返回 200+,且executions总和远小于parse_calls总和,就是典型非绑定变量风暴 - 此时直接看这些语句的
sql_text开头几十个字符,大概率都是SELECT * FROM order WHERE status = 1、... status = 2、... status = 3这种模式
真正难的不是查出来,而是确认哪些 SQL 属于“业务上必须动态拼接、无法改绑定变量”的例外——比如某些报表导出接口按用户传参生成列别名,这种得单独标记,避免误杀。ASH 给的是时间切片证据,FORCE_MATCHING_SIGNATURE 给的是文本聚类证据,两者叠在一起,才能把噪音滤干净。











