v$active_session_history是Oracle负载突变时最灵敏的切入点,每秒采样前台会话,通过session_state、event、sql_id快速定位CPU、I/O或锁争用根因,但数据仅内存保留约1小时。
oracle系统负载突变时,v$active_session_history 是最直接、最灵敏的切入点——它每秒采样一次活跃会话,不依赖快照周期,能捕获秒级尖刺。awr 快照默认一小时一次,等它“反应过来”,问题早结束了。
查最近几分钟的活跃会话分布(实时定位热点)
负载刚飙升时,第一反应不是翻 AWR,而是立刻查内存中的 ASH 实时视图。重点看 session_state、event、sql_id 三列:
-
session_state = 'ON CPU'且占比高 → CPU 密集型问题,比如未绑定变量导致硬解析风暴、或某个 SQL 执行计划退化 -
event大量为db file sequential read或direct path read→ I/O 瓶颈,常伴随全表扫描或大排序 -
event集中在enq: TX - row lock contention或latch: cache buffers chains→ 并发争用,可能是热点块或事务阻塞 - 注意过滤掉后台线程:
session_type = 'FOREGROUND',避免被CKPT、DBW0等干扰判断
示例语句(查最近 5 分钟):
SELECT sql_id, event, session_state, COUNT(*) cnt FROM v$active_session_history WHERE sample_time > SYSDATE - 5/(24*60) AND session_type = 'FOREGROUND' GROUP BY sql_id, event, session_state ORDER BY cnt DESC;
按等待事件反推 SQL 和会话(快速关联根因)
ASH 不是孤立数据,它和 v$sql、v$session 可直接关联。一旦发现某类等待事件集中爆发,立刻顺藤摸瓜:
- 用
sql_id查原始语句:SELECT sql_text FROM v$sql WHERE sql_id = '&sql_id' AND ROWNUM (加 <code>ROWNUM防止长文本卡住) - 查具体会话状态:
SELECT sid, serial#, username, program, blocking_session FROM v$session WHERE sql_id = '&sql_id' - 若等待事件含锁信息(如
enq: TX),必须查blocking_session和final_blocking_session,否则永远只看到“被堵者” - 注意:
v$active_session_history中的sql_id可能为空(比如解析失败、PL/SQL 匿名块),此时要结合program和module判断来源
为什么 ASH 报告有时查不到刚发生的异常?
不是脚本写错,是 ASH 数据本身有生命周期限制:
- Oracle 默认只在内存中保留约 1 小时的 ASH 样本(实际取决于
_ash_size隐含参数和 SGA 分配),超出即被覆盖 - 执行
@?/rdbms/admin/ashrpt.sql时,如果指定的时间范围跨了内存已丢弃的区间,报告里就“断层”——尤其在低负载实例上,ASH 缓冲区可能几分钟就刷空 - 解决方案不是等,而是主动干预:
EXEC DBMS_WORKLOAD_REPOSITORY.CREATE_SNAPSHOT()可强制将当前内存 ASH 快照持久化进 AWR,后续再生成 ASH 报告就能覆盖更长时间 - 但要注意:频繁手动打快照会增加 AWR 表空间压力,生产环境建议只在确认突变发生后立即执行一次
ASH 报告 vs AWR 报告:什么时候该用哪个?
别被名字带偏——ASH 报告不是 AWR 的“简化版”,它是不同维度的工具:
- 查“**刚才那 30 秒到底发生了什么**” → 用
v$active_session_history查询或生成短时 ASH 报告(@?/rdbms/admin/ashrpt.sql,时间范围设为 60–300 秒) - 查“**过去两小时整体负载趋势、TOP SQL 排名变化、ADDM 给了什么建议**” → 用 AWR 报告(
@?/rdbms/admin/awrrpt.sql),尤其关注报告里嵌入的 ASH 摘要章节(Oracle 19c+) - 两者结合才完整:AWR 告诉你“哪段时间出问题”,ASH 告诉你“那段时间里每个会话在干什么”。跳过任意一环,都容易把根因归错
真正容易被忽略的,是 ASH 的采样精度边界:它每秒一次,但不保证捕获所有亚秒级操作;一个执行 300ms 的 SQL,有约 30% 概率在单次采样中被漏掉。所以看到“无明显 TOP SQL”,别急着下结论——扩大时间窗口重查,或配合 OS 层 top -Hp + oradebug 追踪线程级行为。


















