遇到 Oracle ASH 数据看起来“不足”或“不完整”时,先别急着判断数据丢失,应该先确认statistics_level是否设置为TYPICAL;然后再逐项排查,看看是不是_ash_size设置过小、查询的采样时间范围选得不够准确,或者当前问题本身就更适合转到dba_hist_active_sess_history中查询历史 ASH 数据。

ASH 数据看似“不足”通常并不是凭空消失,而是已经被覆盖,或者当时根本没有采集到——首先要分清究竟是内存缓冲不足、采样功能失效,还是 ASH 查询方式本身有问题。
查不到数据?先确认 statistics_level 是否为 TYPICAL
这是 Oracle ASH 采样最容易被忽视的关键开关。如果它被设置成 ALL 或 BASIC,v$active_session_history 可能会完全没有数据,结果就是一行记录都查不到。
SELECT name, value FROM v$parameter WHERE name = 'statistics_level';—— 结果必须返回TYPICAL- 修改方式很简单:
ALTER SYSTEM SET statistics_level = typical SCOPE = BOTH;,通常不需要重启数据库 - 如果是 RAC 环境,每个节点、每个实例都要分别检查,不能只确认其中一个
v$active_session_history 保留时间太短?大概率是 _ash_size 偏小
默认只有 4MB 的内存缓冲区,在高并发或高负载场景下,往往只能保留 10 到 15 分钟左右的 ASH 数据。如果查询 MIN(sample_time) 和 MAX(sample_time) 后发现时间跨度只有几分钟,基本可以判断是 ASH buffer 被快速覆盖了。
- 扩容通常需要调整隐含参数:
ALTER SYSTEM SET "_ash_size" = 524288000 SCOPE = SPFILE;(这里是 500MB 示例) - 同时还必须同步增大
sga_max_size,否则数据库下次启动时可能失败 - 修改后需要重启实例才能生效,不能通过
SCOPE=BOTH在线立即生效 - 也不要盲目把值调得过大——超过 30MB Oracle 可能不接受,而且过大的 ASH 区域也会挤占其他 SGA 组件资源
想查“最近一分钟”却总是漏掉数据?不要直接用 SYSDATE - 1/1440
ASH 采样并不是严格均匀的固定节拍,虽然平均大约每秒一次,但实际采样间隔会有波动。若直接使用模糊的时间范围条件,往往容易刚好错过整个采样窗口,最终导致查询不到任何记录。
- 更稳妥的做法是使用精确时间范围:
SAMPLE_TIME BETWEEN TIMESTAMP '2026-07-21 19:30:00' AND TIMESTAMP '2026-07-21 19:31:00' - 如果不确定具体的秒级时间点,可以先通过
dba_hist_active_sess_history粗略定位时间区间(它通常每 10 秒保留一次,时间覆盖更稳定) - 对于持续时间短于 500ms 的瞬时事件,本来就可能无法被 ASH 捕获,因为 ASH 并不是为这种超细粒度分析设计的
历史问题在实时视图里查不到?转向 dba_hist_active_sess_history 和 AWR 快照
v$active_session_history 属于内存视图,天然会被覆盖、也容易丢失;而 dba_hist_active_sess_history 则是落盘后的持久化历史数据,只要 AWR 采集机制运行正常,就可能保留数天、数周,甚至更长时间的性能信息。
- 先确认 AWR 快照是否正常生成:
SELECT COUNT(*) FROM dba_hist_snapshot WHERE end_interval_time > SYSDATE - 1; - 查询历史 ASH 数据:
SELECT * FROM dba_hist_active_sess_history WHERE sample_time BETWEEN ... - 需要注意的是:它通常只保留大约 10% 的原始 ASH 采样,因此细节粒度不如内存中的 ASH,但时间覆盖范围更长
- 某些场景下(例如凌晨短时抖动或夜间异常),实时内存视图里的数据可能早已被覆盖,但
awr_pdb_active_sess_history中仍可能保留关键线索
真正难处理的地方,往往不是 Oracle 参数该怎么调整,而是先把问题性质判断准确:到底是“当时根本没有采到”,还是“已经采集到了,只是后来被覆盖掉了”。这两种情况表面上都像是 ASH 数据不足,但排查思路完全不同。前一种情况,应优先检查 statistics_level 是否正确开启,再确认 MMNL 进程是否正常存活;后一种情况,才需要进一步考虑是否调整 _ash_size。在实际运维中,很多人一上来就急着加大内存,结果折腾很久才发现,ASH 采样功能当时其实根本没启用。
