默认情况下V$ACTIVE_SESSION_HISTORY只保留最近60分钟数据,查历史故障须用DBA_HIST_ACTIVE_SESS_HISTORY并以sample_time过滤;定位CPU 100%需筛选session_state='ON CPU'且session_type='FOREGROUND',按sql_id等分组统计;执行计划需关联DBA_HIST_SQL_PLAN并匹配dbid与instance_number。
ASH视图查不到过去1小时以外的数据?
默认情况下,oracle的v$active_session_history只保留最近60分钟的采样(实际受dba_hist_active_sess_history归档策略影响),直接查v$视图必然漏掉历史故障。必须切到历史表,且注意时间字段是sample_time而非sql_exec_start。
- 用
DBA_HIST_ACTIVE_SESS_HISTORY查超过1小时的记录,它按AWR快照周期归档(默认每小时1次,但采样粒度仍是1秒) -
sample_time是采样发生时间,精度为秒;故障时刻要落在这个时间点上,不能只靠SQL执行开始/结束时间过滤 - 确认AWR保留期:
SELECT retention FROM dba_hist_wr_control,低于7天可能已自动清理
定位CPU 100%时谁在“吃”CPU?
ASH里session_state = 'ON CPU'表示该会话正在消耗CPU,不是等待。但单看这一列不够——得聚合出高CPU贡献者,同时排除系统后台进程干扰。
- 关键过滤条件:
session_state = 'ON CPU' AND session_type = 'FOREGROUND'(排除BACKGROUND如DBWR、LGWR) - 按
sql_id+program+module分组统计COUNT(*),值越高说明该SQL/程序在故障窗口内占CPU采样越多 - 别忽略
blocking_session和event:如果大量会话卡在enq: TX - row lock contention,真实瓶颈可能是锁,不是CPU本身
SELECT sql_id, program, module, COUNT(*) cnt FROM dba_hist_active_sess_history WHERE sample_time BETWEEN TIMESTAMP '2024-05-20 14:30:00' AND TIMESTAMP '2024-05-20 14:35:00' AND session_state = 'ON CPU' AND session_type = 'FOREGROUND' GROUP BY sql_id, program, module ORDER BY cnt DESC FETCH FIRST 5 ROWS ONLY;
为什么查到了高CPU SQL,却找不到对应执行计划?
DBA_HIST_ACTIVE_SESS_HISTORY只存sql_id,不存执行计划。想还原当时的真实执行路径,得去DBA_HIST_SQL_PLAN或DBA_HIST_SQLTEXT里捞,但要注意时间匹配和版本有效性。
-
DBA_HIST_SQL_PLAN里的plan_hash_value可能和当前不同——同一sql_id在不同时间可能走不同执行计划 - 查计划时务必带上
dbid和instance_number,否则跨RAC或跨库容易拿错环境数据 - 如果
DBA_HIST_SQLTEXT里查不到该sql_id,说明SQL已被老化出共享池,或AWR未捕获其文本(需检查STATISTICS_LEVEL是否为TYPICAL或ALL)
时间范围选窄了反而看不到根因?
CPU飙升常是连锁反应:一个慢SQL堵住连接池 → 应用重试 → 更多会话堆积 → CPU被线程调度、锁争用等间接拉满。只盯峰值那1分钟,可能只看到“症状”,看不到“病源”。
- 建议把时间窗口往前扩5–10分钟:从CPU开始爬升的拐点起查,而不是从100%顶点开始
- 关注
event分布变化趋势:比如前3分钟大量db file sequential read,后2分钟突然全变ON CPU,说明I/O压力触发了后续CPU争抢 - 结合
DBA_HIST_SYSMETRIC_HISTORY里的CPU Usage Per Sec指标交叉验证,避免ASH采样偏差导致误判
ASH不是万能快照,它只反映“谁在CPU上”,不解释“为什么上来”。真正难的永远是把sql_id和业务操作、应用线程模型、数据库参数设置串起来——这部分没有视图能自动告诉你。

















