删除awr快照前须确认dba_hist_snapshot中目标快照status=0且无ash引用;drop_snapshot_range参数需为number类型、闭区间;删后需shrink space释放空间,长期应调整retention策略。
直接删快照前先确认 dba_hist_snapshot 里有没有被锁住的快照
oracle 不允许直接删正在被其他会话引用(比如 awr 报告生成中)或未归档的快照,强行删会报 ora-13516 或卡在 dbms_workload_repository.drop_snapshot_range 调用里。必须先查清楚当前快照状态:
- 运行
SELECT snap_id, status, begin_interval_time FROM dba_hist_snapshot WHERE snap_id BETWEEN X AND Y ORDER BY snap_id;确认目标范围是否全为STATUS = 0(正常完成),非 0 值(如 1=正在生成、2=失败)不能删 - 检查是否有活跃的 AWR 报告依赖:执行
SELECT * FROM dba_hist_active_sess_history WHERE snap_id IN (X,Y);,若返回结果,说明快照仍被 ASH 数据引用,需等报告生成结束或手动清理相关临时对象(极少见,通常等几分钟再试)
DBMS_WORKLOAD_REPOSITORY.DROP_SNAPSHOT_RANGE 的参数陷阱
这个过程看着简单,但两个参数顺序和类型错一个就静默失败或删错范围:
-
low_snap_id和high_snap_id是 包含两端 的闭区间,不是“从 low 到 high-1” - 两个参数都必须是
NUMBER类型,传字符串(比如'1234')会报PLS-00306;传 NULL 会直接报错退出,不提示 - 执行前务必用
SELECT MIN(snap_id), MAX(snap_id) FROM dba_hist_snapshot;核对边界值,避免因快照 ID 断层导致误删——例如你只想删 1000–1050,但实际最大只有 1040,high_snap_id=1050不会报错,而是只删到 1040
删完快照后 SYSAUX 表空间不缩容?别急着 ALTER DATABASE DATAFILE ... RESIZE
AWR 数据删掉只是标记为可重用,段(segment)不会自动收缩,SYSAUX 里的 WRH$_* 表高水位线还在,空间不会还给操作系统:
- 先跑
EXEC DBMS_STATS.GATHER_SCHEMA_STATS('SYS', cascade => TRUE);更新统计信息,否则后续查询dba_segments可能不准 - 查大对象:
SELECT segment_name, bytes/1024/1024 MB FROM dba_segments WHERE tablespace_name = 'SYSAUX' AND segment_name LIKE 'WRH$%' ORDER BY bytes DESC; - 真正释放空间得靠
ALTER TABLE sys.<code>WRH$_XXXSHRINK SPACE CASCADE;,但注意:必须开启行移动(ALTER TABLE sys.<code>WRH$_XXXENABLE ROW MOVEMENT;),且该操作会锁表几秒——建议在维护窗口做,别在业务高峰期跑
替代方案:改 retention 比手动删更稳
如果目标是长期控 SYSAUX 大小,硬删快照是治标;调整保留策略才是根治:
- 查当前设置:
SELECT retention FROM dba_hist_wr_control; - 设为 7 天(单位是分钟):
EXEC DBMS_WORKLOAD_REPOSITORY.MODIFY_SNAPSHOT_SETTINGS(retention => 7*24*60); - 注意:新设置只影响后续快照,已存在的老快照不会自动清理,仍需手动删一次;但之后 Oracle 会每天自动 purge 过期数据,比人工干预可靠得多
- 如果 SYSAUX 已严重膨胀(>30GB),先删快照 + shrink,再调 retention,否则自动 purge 可能慢到像没发生一样
最常被忽略的一点:DROP_SNAPSHOT_RANGE 不会清理 WRM$_* 管理表里的元数据记录,这些小记录堆积多年也会占几十 MB。真要彻底瘦身,得配合 DBMS_WORKLOAD_REPOSITORY.AWR_PURGE(12c+)或手工 truncate(需极高权限,风险自担)。










