最可靠轻量的离线ash分析方式是直接运行@?/rdbms/admin/ashrpt.sql生成html报表,无需导出原始数据,不依赖oem或pl/sql包;其自动聚合多维信息、支持交互式诊断,且输出文件位于sql*plus当前工作目录。

直接用 @?/rdbms/admin/ashrpt.sql 生成 HTML 报表,就是最可靠、最轻量的离线分析方式——不需要额外导出原始数据,也不依赖 OEM 或 PL/SQL 包。
为什么不用先“导出ASH原始数据”再分析
很多人误以为要先把 V$ACTIVE_SESSION_HISTORY 的内容 SELECT ... INTO OUTFILE 或导出为 CSV,再用 Excel/Python 分析。这既不可行也不必要:
- ASH 内存缓冲区中的数据是循环覆盖的,
SELECT出来的只是快照,无法还原采样时序和会话关联关系 -
V$ACTIVE_SESSION_HISTORY不支持直接导出(无对应 Data Pump 对象,expdp不识别该视图) - 脚本
ashrpt.sql本身已封装了完整的聚合逻辑:按 SQL_ID、等待事件、对象 ID、阻塞链等多维归因,且自动过滤空闲会话 - 生成的 HTML 报表自带交互式折叠、跳转链接(如点击 SQL_ID 可定位到执行计划节)、颜色热区(高亮 Top Event),比原始 CSV 更适合离线诊断
ashrpt.sql 必须输对的三个交互项
启动 SQL*Plus 后执行 @?/rdbms/admin/ashrpt.sql,关键交互点只有三个,错一个就可能报空或报错:
-
Enter value for report_type:—— 直接回车(默认html),或输入html(全小写、无空格)。输HTML、text后想改?不行,必须退出重进;输错会触发SP2-0310: unable to open file "ashrpt_HTML.sql" -
Enter begin time for report:—— 推荐用相对时间,例如-30(30 分钟前)或-1:15(1 小时 15 分钟前)。绝对时间格式必须是MM/DD/YY HH24:MI:SS,如10/01/26 14:30:00;月份/日期/年份顺序颠倒、年份写四位(2026)都会被忽略 -
Enter value for report_name:—— 务必带后缀,如ash_20261002.html。不加.html会导致文件不可直接双击打开,某些终端也认不出 MIME 类型
时间范围填错=报表为空,不是 bug 是设计
ASH 报表为空,90% 是因为时间范围超出了内存缓冲区保留窗口:
- Oracle 19c 默认 ASH buffer 约保留
60分钟(实际受 SGA 分配和负载影响,可能短至 20 分钟) - 你输入
begin_time为-120(2 小时前),哪怕duration只设 5 分钟,结果也基本为空——因为那段时间的数据早已被 MMNL 进程覆盖 - 查当前缓冲区是否还有数据?在 SQL*Plus 中运行:
SELECT MIN(sample_time), MAX(sample_time) FROM v$active_session_history;。如果返回空,说明缓冲区当前无有效采样,此时任何ashrpt.sql调用都无效 - 注意:
duration单位是分钟,不是秒。文档里写 “seconds” 是历史遗留错误,实测输30就是 30 分钟
生成的 HTML 文件在哪?别去 $ORACLE_HOME 翻
文件不会落在 Oracle 安装目录下,它严格生成在你启动 SQL*Plus 时的当前工作目录:
- Linux 下执行
!pwd,Windows 下执行!cd,就能确认路径 - 比如你在
/home/oracle/diag下运行sqlplus / as sysdba,那ash_20261002.html就在/home/oracle/diag/下 - 别指望它自动保存到 AWR 目录或
$ORACLE_HOME/rdbms/admin/—— 那里只有脚本,没有输出 - 需要传到本地看?用
scp或lrzsz(sz ash_20261002.html)即可,别花时间在错误路径里搜索
真正容易被忽略的是:ASH 报表的诊断价值高度依赖时间精度。如果你只记得“大概一小时前卡过”,但没记准具体分钟,生成的报表可能刚好错过峰值窗口——建议配合 DBA_HIST_ACTIVE_SESS_HISTORY(AWR 持久化版)做交叉验证,尤其当问题发生在 1 小时前又没开 AWR 快照时。











