ash不能真正还原会话活动,仅能重建关键片段;v$active_session_history数据存于sga内存,默认保留约60分钟,高并发下可能缩至10–20分钟,超时即被覆盖,断电重启后全清空。

ASH 不能真正“还原”会话活动,只能重建关键片段——它不是录像,是每秒一张快照的胶片,漏帧、压缩、丢细节是常态。
为什么直接查 v$active_session_history 找不到昨天的会话
该视图数据存在 SGA 内存中,受 _ash_size 隐含参数和系统负载双重限制。默认保留约 60 分钟,高并发下可能缩至 10–20 分钟。一旦缓冲区满,旧样本就被覆盖,断电或重启后全清空。
- 查不到历史?先确认时间范围是否在内存窗口内:执行
SELECT MIN(sample_time), MAX(sample_time) FROM v$active_session_history; - 想查 1 小时前的数据但返回空?大概率已被覆盖,别硬刷,转去磁盘历史表
- 不要用
SYS_CONTEXT('USERENV', 'SID')或当前v$session.sid去匹配历史采样——会话已断开,SID 可能被复用
查 dba_hist_active_sess_history 的三个硬约束
这是 AWR 快照落盘后的 ASH 副本,采样频率降为每 10 秒一次(非实时每秒),且只保留活跃会话。它适合归因,不适用于精确定位。
- 必须带时间条件:用
sample_time BETWEEN ... AND ...,别只靠sql_id或session_id单字段过滤——历史表里同一sql_id出现上千次很常见 - 必须加
WHERE event NOT IN ('SQL*Net message from client', 'PL/SQL lock timer')排除空闲等待,否则结果里 90% 是假阳性 - 注意
blocking_session字段在历史表中可能为 NULL —— 因为采样间隔拉长后,死锁链的瞬时互指关系大概率丢失,得回溯到v$active_session_history实时窗口里抓
current_obj# 和 sql_id 能不能定位具体 SQL 或对象
可以辅助判断,但不能单独依赖。
-
current_obj#是对象编号,需关联dba_objects.object_id查名称;但它只在采样瞬间持有该对象锁或正在访问时才非空,短事务可能全程没被捕获 -
sql_id对应的是共享池中的语句哈希,不是文本。想看 SQL 内容,得用SELECT sql_text FROM dba_hist_sqltext WHERE sql_id = 'xxx';—— 但要注意:若该 SQL 已被 aged out,dba_hist_sqltext里可能为空 - 绑定变量值?ASH 不存。别指望从
dba_hist_active_sess_history里捞出:B1 = '2026-07-20'这类信息,它压根没采集
最容易被忽略的采样盲区
ASH 天然漏掉三类关键场景,查之前心里要有数:
- 执行耗时 100 时
- SQL 执行完、结果集未取完的阶段:此时会话处于
SQL*Net message from client等待,ASH 认为“非活跃”,不采样 - PL/SQL 执行中的纯计算(无 SQL、无等待):CPU 时间不触发等待事件,ASH 只记录“ON CPU”状态,但不区分是逻辑读多还是循环计算多
所以当你发现某条慢查询在 ASH 里“查无此 SQL”,未必是没执行,更可能是它太快、太安静、或者卡在客户端没发 fetch 请求。











