ASH可直接定位实时高消耗SQL:每秒采样ON CPU会话,关联sql_id与执行堆栈;若无sql_id,需查session_type、program及event;查不到数据时须确认statistics_level非BASIC、实例已运行足够时间且非RAC跨节点误查。
直接查 v$active_session_history 找实时高消耗 SQL
oracle 11g 开始,v$active_session_history(ash)是比 v$session 更可靠的第一手线索——它每秒采样一次活跃会话,不依赖 sql 是否已执行完,也不受硬解析掩盖影响。cpu 飙到 100% 时,v$session 可能只显示 on cpu 状态,但看不到具体 sql;而 ash 能直接关联到正在燃烧 cpu 的 sql_id 和执行堆栈。
执行以下查询(建议限定最近 5 分钟):
SELECT sql_id, sql_plan_hash_value, event, COUNT(*) cnt FROM v$active_session_history WHERE session_state = 'ON CPU' AND sample_time > SYSDATE - 5/1440 GROUP BY sql_id, sql_plan_hash_value, event ORDER BY cnt DESC FETCH FIRST 10 ROWS ONLY;
- 如果返回多条记录中某
sql_id占比远超其他(比如 >30%),基本就是元凶 -
sql_plan_hash_value不同但sql_id相同,说明同一 SQL 因绑定变量或统计信息变化走了不同执行计划,需分别检查 - 若大量行的
event是db file sequential read或direct path read,实际瓶颈在 I/O,不是纯 CPU 问题,别被 top 表象误导
ASH 查不到 SQL?重点看 session_type 和 program
有时 v$active_session_history 里确实没有 sql_id,但 session_state = 'ON CPU' 的记录依然密集。这时候要盯住 session_type 和 program 字段:
-
session_type = 'BACKGROUND':可能是DBWR、LGWR或CKPT进程异常,比如检查点频繁触发或写入压力过大,需结合AWR中Background CPU Time指标确认 -
program包含oracle@... (J00):说明是 job queue slave 在跑 PL/SQL,常见于未加限制的批量循环(如FOR i IN 1..1000000 LOOP ... END LOOP;),这类代码不会出现在v$sql,但会持续占 CPU -
program是oracle@... (TNS V1-V3)且module为空:大概率是应用端连接池未复用、反复建连接 + 解析,造成大量硬解析——此时sql_id为0000000000000000或全空,ASH中表现为高频PARSE相关等待(如cursor: pin S wait on X)
拿到 sql_id 后,别急着 kill,先看执行计划和真实资源消耗
查到可疑 sql_id 后,用 DBMS_XPLAN.DISPLAY_CURSOR 查真实执行计划,注意三个关键点:
- 看
Rows列:如果预估Rows是 1,但实际A-Rows是百万级,说明统计信息严重过期,优化器选错了路径 - 找
TempSpc列非空的操作:意味着排序或哈希连接用了临时表空间,这类操作天然吃 CPU,尤其当PGA_AGGREGATE_TARGET设置过小导致频繁写磁盘时 - 检查是否出现
PARALLEL关键字:即使 SQL 没写 hint,也可能因对象级别设置了DEGREE > 1,一个 SQL 拉起 8 个 PX 进程,CPU 瞬间拉满
执行示例:
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR('fm0738ywgbyxk', NULL, 'ALLSTATS LAST'));
为什么 ASH 有时查不到数据?注意采样窗口和保留时间
v$active_session_history 是内存视图,数据默认只保留约 1 小时(受 _ash_size 和 _ash_disk_filter_ratio 影响),且依赖 STATISTICS_LEVEL = TYPICAL(默认值)。如果查不到记录,先确认:
- 当前实例是否启用了 ASH:
SELECT value FROM v$parameter WHERE name = 'statistics_level';—— 若返回BASIC,则ASH完全不工作 - 是否刚重启过数据库?内存中 ASH 数据已清空,需等新采样积累
- 是否在 RAC 环境?必须在本地实例查,不能跨节点聚合;若需全局视角,得用
dba_hist_active_sess_history(AWR 快照),但延迟至少 10 分钟
真正棘手的情况是:ASH 显示大量 ON CPU,但 sql_id 全为空、program 是 oracle@... (P00)、event 是 PGA memory operation ——这往往指向底层 PGA 内存管理缺陷或 Oracle Bug,11.2.0.4 以前版本在高并发短连接场景下容易触发,升级补丁比调优更有效。











