先查绑定变量窥视是否导致计划跳变,因ON CPU但SQL执行快说明CPU消耗在解析而非执行;需验证同一sql_id是否对应多个sql_plan_hash_value,并检查v$sql_shared_cursor中BIND_MISMATCH/UNBOUND_CURSOR=Y等伪共享信号。
ASH里看到ON CPU但SQL执行快,先查是不是绑定变量窥视在作怪
当v$active_session_history中大量样本显示session_state = 'on cpu',而对应sql_id在v$sql里的elapsed_time/executions却只有几毫秒,说明cpu没花在sql扫描上,大概率是硬解析或计划跳变导致的反复解析开销。绑定变量窥视(bind peeking)正是这类问题的典型诱因——第一次执行时peek到一个极端值(比如高频值),生成了全表扫描计划并缓存;后续传低频值时仍复用该计划,但优化器在运行时发现实际行数远少于估算,触发acs机制尝试生成新子游标,过程中大量cpu消耗在library cache lock、cursor pin、row cache lock等内部争用上。
查ASH里同一个sql_id是否对应多个sql_plan_hash_value
绑定变量窥视引发计划跳变的直接证据,就是同一sql_id在ASH中分散在多个不同执行计划上。这说明Oracle正在为不同绑定值维护多个子游标,而切换过程本身就有开销。
- 执行:
SELECT sql_plan_hash_value, COUNT(*) FROM v$active_session_history WHERE sql_id = '<target_sql_id>' AND session_state = 'ON CPU' GROUP BY sql_plan_hash_value ORDER BY COUNT(*) DESC - 如果返回2个以上
sql_plan_hash_value,且分布较散(比如各占30%、40%、30%),基本坐实ACS正在动态适配,但未收敛 - 注意:若只返回1个hash value,但
v$sql_shared_cursor里BIND_MISMATCH = 'Y'或UNBOUND_CURSOR = 'Y',说明游标根本没共享,每次都在硬解析——这比ACS更糟
结合v$sql_shared_cursor和v$sql找出“伪共享”信号
绑定变量窥视真正落地为性能问题,一定伴随游标无法稳定复用。不能只看v$sql的parse_calls,得确认这些解析是不是有效复用。
-
SELECT parse_calls, executions, loads, invalidations FROM v$sql WHERE sql_id = '<target_sql_id>'—— 若parse_calls >> executions(比如1000次解析、50次执行),就是硬解析风暴 -
SELECT * FROM v$sql_shared_cursor WHERE sql_id = '<target_sql_id>' AND (BIND_MISMATCH = 'Y' OR UNBOUND_CURSOR = 'Y' OR OPTIMIZER_MISMATCH = 'Y')—— 出现任意Y,说明每次执行都因绑定值差异被迫走新解析路径 - 特别留意
TRANSLATION_MISMATCH:RAC环境下不同实例的NLS设置不一致,也会让同一sql_id无法共享,表面像绑定变量问题,实则是环境配置漂移
别只盯着sql_id,要顺藤摸瓜看blocking_session和final_blocking_session
ASH里sql_id字段在ON CPU状态下常失真——PL/SQL循环里执行的查询,sql_id记录的是过程名;硬解析卡在library cache lock时,sql_id是待解析语句,但样本实际耗在锁持有者身上。这时候必须跳出单条SQL视角。
- 查当前会话真实阻塞链:
SELECT sid, blocking_session, final_blocking_session, event, p1text, p1 FROM v$session WHERE sql_id = '<target_sql_id>' AND state = 'ON CPU' - 若
blocking_session为空但final_blocking_session有值,说明存在级联阻塞(A锁B、B锁C),需顺着final_blocking_session查下去 - 若
event是library cache lock或row cache lock,且p1text为handle address,p1值相同,就指向同一个库缓存对象——大概率是这个SQL的解析正在被其他会话抢占
绑定变量窥视本身不会直接卡住数据库,但它会让执行计划变得脆弱,一旦统计信息更新、绑定值突变或游标老化,就会触发连锁反应。最麻烦的是问题只在特定时间窗口出现,比如每天凌晨统计信息收集后那一小时——这时候ASH采样窗口必须精确到分钟级,且要同步比对dba_hist_sqlbind里历史绑定值分布,才能把“为什么这次peek错了”说清楚。



















