内存中v$active_session_history仅保留约1小时数据,提取历史两小时ash报告必须使用dba_hist_active_sess_history和dbms_workload_repository.ash_report_html,指定dba_hist_ash_snapshot中真实存在的end_interval_time快照时间点。

直接说结论:内存中 V$ACTIVE_SESSION_HISTORY 只保留约 1 小时数据,要提取“历史特定两小时”的 ASH 报告,必须依赖 AWR 中持久化的 DBA_HIST_ACTIVE_SESS_HISTORY,不能只靠脚本交互式生成——否则会报错或数据缺失。
为什么 ashrpt.sql 默认无法导出超过1小时的历史区间
执行 @?/rdbms/admin/ashrpt.sql 时,若输入的起始时间早于当前时间减 60 分钟(例如 -2:00),脚本会尝试从内存视图查数据,但 V$ACTIVE_SESSION_HISTORY 已被覆盖。此时报告可能为空、仅含零星样本,或直接提示“no data found”。这不是脚本问题,是内存环形缓冲区设计决定的——ASH 缓冲区默认上限约 30MB,高负载下实际保留时间可能不足 45 分钟。
- 检查当前内存中可用时间范围:
SELECT MIN(sample_time), MAX(sample_time) FROM V$ACTIVE_SESSION_HISTORY; - 确认 AWR 中是否有对应历史数据:
SELECT MIN(sample_time), MAX(sample_time) FROM DBA_HIST_ACTIVE_SESS_HISTORY WHERE sample_time BETWEEN SYSDATE-2 AND SYSDATE; - 若后者有数据而前者无,则必须走 AWR 回填路径,而非交互式脚本
用 DBMS_WORKLOAD_REPOSITORY.ASH_REPORT_HTML 生成跨小时报告
这是唯一可靠提取“历史两小时”ASH数据的方式:绕过内存限制,显式指定 AWR 中已归档的采样时间边界。关键点在于传入的两个 END_INTERVAL_TIME 必须来自 DBA_HIST_ASH_SNAPSHOT(不是任意时间戳),且时间跨度需覆盖目标区间。
- 先查快照时间锚点:
SELECT SNAP_ID, BEGIN_INTERVAL_TIME, END_INTERVAL_TIME FROM DBA_HIST_ASH_SNAPSHOT WHERE END_INTERVAL_TIME BETWEEN SYSDATE-2 AND SYSDATE ORDER BY SNAP_ID DESC; - 选相邻两个快照,确保其
END_INTERVAL_TIME覆盖你要分析的两小时起点和终点(例如 SNAP_ID=3116 的END_INTERVAL_TIME是 14:00,SNAP_ID=3118 的是 16:00,则用这两个) - 调用存储过程(注意 DBID 和 INSTANCE_NUMBER 需匹配当前库):
SELECT * FROM TABLE(DBMS_WORKLOAD_REPOSITORY.ASH_REPORT_HTML( <code>3424884828</code>, -- 替换为你的 DBID <code>1</code>, -- 实例号 (SELECT END_INTERVAL_TIME FROM DBA_HIST_ASH_SNAPSHOT WHERE SNAP_ID = <code>3116</code>), (SELECT END_INTERVAL_TIME FROM DBA_HIST_ASH_SNAPSHOT WHERE SNAP_ID = <code>3118</code>) ));
- 结果是 CLOB,复制内容到文件,保存为
.html后缀即可浏览器打开
常见错误:时间参数填错导致报告空白
最常踩的坑是把 BEGIN_INTERVAL_TIME 或任意字符串时间硬编码进 ASH_REPORT_HTML,Oracle 会静默忽略错误并返回空结果。这个函数只认 DBA_HIST_ASH_SNAPSHOT 中真实存在的 END_INTERVAL_TIME 值,且要求两个时间点必须在同一个 AWR 保留周期内(默认 8 天),超出则查不到快照记录。
- 错误示例:
TO_DATE('2026-09-15 14:00:00', 'YYYY-MM-DD HH24:MI:SS')—— 不合法,函数不接受 raw timestamp - 正确做法:始终用子查询从
DBA_HIST_ASH_SNAPSHOT拉取,且确保SNAP_ID存在(SELECT COUNT(*) FROM DBA_HIST_ASH_SNAPSHOT WHERE SNAP_ID = 3116) - 如果目标时间跨了数据库重启,需确认
STARTUP_TIME是否包含该区间(DBA_HIST_ASH_SNAPSHOT.STARTUP_TIME字段)
真正难的不是调用函数,而是确认那两小时的数据确实落盘到了 AWR。高负载下 MMNL 进程只写入约 10% 的 ASH 样本,所以即使时间对得上,报告里也可能只有部分会话——这时得结合 DBA_HIST_SQLSTAT 和 V$SQL 补全 SQL 执行细节。











