安全手动创建AWR快照需确认快照ID、避开高并发时段、容忍重启后首次延迟;删除前须验证STATUS全为0且ASH无引用,删除后SYSAUX不自动收缩,应优先调整retention而非硬删。

DBMS_WORKLOAD_REPOSITORY.CREATE_SNAPSHOT() 和 DBMS_WORKLOAD_REPOSITORY.DROP_SNAPSHOT_RANGE() 是 Oracle 11g 中手动管理 AWR 快照最直接的两个入口。但直接执行命令容易失败或留下隐患,关键不在“会不会写”,而在“什么时候能删、删完要不要收尾”。
怎么安全地手动创建一个快照
CREATE_SNAPSHOT() 看似简单,但实际使用中要注意三点:
- 它不返回快照 ID(除非显式声明变量接收),只返回 PL/SQL 执行成功状态,所以想确认是否真生成了,得立刻查 DBA_HIST_SNAPSHOT
- 不建议在高并发 OLTP 时段频繁调用,单次快照采集会触发大量 SQL 解析、ASH 采样和统计刷新,可能引发短暂 latch 争用
- 如果数据库刚重启过,首次调用可能稍慢——因为需要初始化内存结构,这不是错误,是正常行为
常用做法是:
EXEC DBMS_WORKLOAD_REPOSITORY.CREATE_SNAPSHOT();
SELECT SNAP_ID, BEGIN_INTERVAL_TIME FROM DBA_HIST_SNAPSHOT WHERE SNAP_ID = (SELECT MAX(SNAP_ID) FROM DBA_HIST_SNAPSHOT);
删快照前必须检查 STATUS 和 ASH 引用
DROP_SNAPSHOT_RANGE() 表面只要传两个 ID,但 Oracle 实际做了三重校验:
- 目标范围内的每个 SNAP_ID 在 DBA_HIST_SNAPSHOT.STATUS 中必须为 0(已完成),值为 1(正在生成)或 2(失败)的快照不能删
- 对应快照区间内的 DBA_HIST_ACTIVE_SESS_HISTORY 记录不能被任何未完成的 AWR 报告引用,否则会卡住或报 ORA-13516
- low_snap_id 和 high_snap_id 必须是 NUMBER 类型,传字符串(如 '1234')会静默失败,不报错也不删
建议删之前先跑这两条:
SELECT SNAP_ID, STATUS, BEGIN_INTERVAL_TIME FROM DBA_HIST_SNAPSHOT WHERE SNAP_ID BETWEEN 1000 AND 1010 ORDER BY SNAP_ID;
SELECT COUNT(*) FROM DBA_HIST_ACTIVE_SESS_HISTORY WHERE SNAP_ID BETWEEN 1000 AND 1010;
DROP_SNAPSHOT_RANGE。
删完快照 SYSAUX 空间不下降?这是正常现象
AWR 快照删除本质是逻辑标记(mark for reuse),不是物理擦除: -WRH$_ 开头的表(如 WRH$_SQLSTAT)高水位线仍在,SYSAUX 表空间不会自动收缩
- 即使 dba_segments 显示这些段占用 MB 数没变,也不代表数据还在——只是空间还没回收
- 真正释放需两步:先 ALTER TABLE sys.<code>WRH$_SQLSTAT ENABLE ROW MOVEMENT,再 ALTER TABLE sys.<code>WRH$_SQLSTAT SHRINK SPACE CASCADE
- 每个 WRH$_ 表都要单独操作,不能批量;且 SHRINK 期间该表会被短时锁住,别在业务高峰跑
长期控 SYSAUX 大小,优先调 retention 而非硬删
手动删快照是救火,不是常态方案: -modify_snapshot_settings(retention => 7*24*60) 把保留时间设为 7 天(单位是分钟),比反复删更可靠
- interval 设为 0 会彻底禁用所有快照(含自动和手动),慎用
- retention 设为 0 表示永久保留,但实际受 SYSAUX 空间限制,到极限仍会报错,不是真正“永久”
复杂点在于:DROP_SNAPSHOT_RANGE 的参数边界是闭区间,但快照 ID 可能有断层;你传 low_snap_id => 1000, high_snap_id => 1050,如果中间缺了 1005 和 1006,它照样删掉存在的 1000–1050,不会报错提醒你漏了——所以删之前务必用 MIN(SNAP_ID)/MAX(SNAP_ID) 核对真实范围。


















