AWR报告中未见异常SQL不等于无问题SQL,因其可能因执行过短、未完成或解析失败而未被v$sql和AWR收录;ASH凭借秒级采样更易捕获ON CPU且sql_id为空的瞬时高CPU事件。

AWR报告里找不到异常SQL,不等于没有问题SQL——更可能是它根本没进SQL统计池,或者压根没执行完就被干掉了。
为什么v$sql和AWR里都查不到高CPU的SQL_ID
Oracle 11g默认对短生命周期SQL有“过滤门槛”:执行时间太短、未完成、或解析失败的语句,不会被写入v$sql,自然也不会出现在AWR的Top SQL列表里。
-
v$sql只收录已成功硬解析+执行至少一次的SQL;若SQL在parse阶段卡死、自旋、或被中断(如客户端断连、超时),sql_id可能为空或不持久化 - AWR的SQL统计依赖
dba_hist_sqlstat,而该视图每小时仅采样一次,且默认跳过executions = 0或elapsed_time = 0的记录 - 遇到
cursor: mutex S争用或kkshGetNextChild自旋类Bug(如Bug 16175381),大量进程卡在解析链表遍历上,此时sql_id常为空,event显示为ON CPU但无关联SQL
ASH比AWR更适合抓这类“闪现型”高CPU
AWR是快照汇总,ASH是秒级采样,对瞬时、高频、短命的CPU消耗更敏感。尤其当v$sql为空时,ASH里的session_state = 'ON CPU'就是唯一线索。
- 查最近15分钟所有ON CPU的后台/前台会话:
SELECT sample_time, session_id, session_serial#, program, event, sql_id, sql_opname FROM v$active_session_history WHERE session_state = 'ON CPU' AND sample_time > SYSDATE - 15/1440 ORDER BY sample_time DESC; - 重点关注
program字段:若大量出现ora_q000_*、ora_mmon_*、ora_cjq0_*,说明是后台维护任务(如自动统计收集、AQ调度)引发的CPU自旋 - 若
sql_id为空但p1text = 'location'、p1 = 123456789(对应kkshGetNextChild等内部函数地址),基本可锁定是mutex争用Bug
硬解析失控时,CPU高但Top SQL“隐身”
当应用漏写绑定变量、NLS参数漂移、或游标共享被破坏,会导致每条SQL都被当成新语句反复硬解析——CPU耗在语法树构建、权限检查、计划生成上,而非执行本身。
- 检查解析效率:
SELECT parse_calls, executions, ROUND(parse_calls/executions, 2) ratio FROM v$sql WHERE sql_id = '&sql_id';—— 若ratio ≈ 1,说明几乎每次执行都在硬解析 - 看全局硬解析压力:
SELECT name, value FROM v$sysstat WHERE name IN ('parse count (hard)', 'execute count');—— 若parse count (hard)/ 小时 > 500,且execute count远高于它,就是硬解析失控信号 - 确认是否绑定变量失效:
SELECT sql_text FROM v$sql WHERE sql_text LIKE '%WHERE id = %' AND sql_text NOT LIKE '%WHERE id = :%';—— 找出含字面量却没用绑定变量的语句
真正难缠的CPU飙高,往往藏在AWR看不见的地方:空sql_id的自旋、后台任务的失控、或是解析链表上的毫秒级争抢。盯住v$active_session_history和v$mutex_sleep_history,比翻Top SQL列表管用得多。


















