使用awrrpt.sql前必须确认快照连续性,因数据库重启会导致startup_time变更,引发ora-13516错误;应查询dba_hist_snapshot验证startup_time一致性,并优先采用时间范围动态调用awr_report_html/text函数。

用 awrrpt.sql 生成报告前必须确认快照连续性
AWR 报告本质是两个快照之间的差值统计,如果中间发生过数据库重启,awrrpt.sql 会直接报错:ORA-13516: AWR snapshot range is invalid。这不是权限或路径问题,而是数据断裂——重启会导致 v$instance 的 startup_time 变更,而 AWR 快照依赖该时间戳做连续性校验。
实操建议:
- 先查最近 20 个快照是否含重启:
SELECT snap_id, begin_interval_time, startup_time FROM dba_hist_snapshot ORDER BY snap_id DESC FETCH FIRST 20 ROWS ONLY,对比startup_time是否一致 - 脚本中不要硬编码
begin_snap和end_snap,改用时间范围动态推算:用DBMS_WORKLOAD_REPOSITORY.AWR_REPORT_HTML或AWR_REPORT_TEXT函数接口,传入start_time和end_time,Oracle 自动找最近的合法快照对 - 若必须用
awrrpt.sql批量调用,得在 shell 中加一层校验逻辑:用sqlplus -s / as sysdba 判断区间内是否单次启动
Python 调用 SQL*Plus 生成 HTML 报告时的路径与字符集陷阱
直接 os.system("sqlplus / as sysdba @/path/to/awrrpt.sql") 极易失败,常见原因不是权限,而是环境变量缺失和终端编码不匹配。
关键点:
-
ORACLE_HOME和PATH必须在 Python 进程里显式设置,不能依赖 shell profile;否则@?/rdbms/admin/awrrpt.sql中的?替换失败,报错SP2-0310: unable to open file "awrrpt.sql" - SQL*Plus 默认用系统 locale 编码输出 HTML,若服务器 locale 是
zh_CN.UTF-8,但邮件客户端(如 Outlook)按gbk解析,中文标题全乱码;解决方案是在 SQL*Plus 启动前加export NLS_LANG=AMERICAN_AMERICA.AL32UTF8 - HTML 报告里的 JS/CSS 是内联的,但部分老版本 Oracle(如 11.2.0.4)生成的 HTML 包含
零宽空格,导致某些邮件网关拒收附件;可在生成后用 Python 的re.sub(r'[\u200B-\u200D\uFEFF]', '', html_content)清洗
用 DBMS_WORKLOAD_REPOSITORY.AWR_REPORT_HTML 绕过交互式脚本
依赖 awrrpt.sql 的交互式流程(手动输 report_type、num_days 等)无法真正自动化。Oracle 提供了 PL/SQL 函数接口,可从任意程序直连调用,省去文件 I/O 和终端模拟。
示例(Python + cx_Oracle):
cursor.callproc("DBMS_WORKLOAD_REPOSITORY.AWR_REPORT_HTML",
[dbid, inst_num, begin_snap, end_snap, 0, report_html])
注意参数顺序和类型:
-
dbid和inst_num必须从v$database和v$instance查出,不能写死;多实例环境尤其要核对inst_name - 第 5 个参数是
rpt_options,设为0表示基础报告,设为8才启用 ADDM 建议(需 license 支持) - 返回的
report_html是 CLOB 类型,需用cursor.var(cx_Oracle.CLOB)接收,再用.read()取字符串
邮件告警阈值应基于 AWR 的聚合指标而非单点采样
别用“DB Time > 100s”这种绝对值做告警——它没上下文。AWR 报告里的 DB Time(s) 是整个采样窗口(比如 1 小时)的总和,而业务负载本身就有峰谷。直接告警会每天半夜误报。
合理做法是计算相对偏离度:
- 取过去 7 天同一时段(如周一 9:00–10:00)的
DB Time均值和标准差,当前值超过均值 + 2σ 才触发 - 重点监控
Top 5 Timed Events中的非空闲等待事件占比,例如db file sequential read占 DB Time 超过 40%,说明 I/O 成瓶颈,比单纯看物理读次数更准 - SQL 级别告警别盯
Elapsed Time,改看Executions×Elapsed Time Per Exec,避免高频轻量 SQL 拉高总量却掩盖低频重 SQL
最易被忽略的是 baseline 的时效性:ADDM 建议依赖 baseline,但默认 baseline 是手动创建的静态快照组。若长期不更新,对比基准失效,告警灵敏度会随时间衰减。











