必须先关闭写入源再清理数据:通过v$sysaux_occupants定位占用模块,禁用对应自动任务(如SM/ADVISOR、ASTS、AUDSYS),再TRUNCATE或迁移相关表,RAC环境下需全库MOUNT状态操作。

SYSAUX 或 SYSTEM 表空间里某个大表段(如 WRI$_ADV_OBJECTS、WRI$_SQLSET_PLAN_LINES、AUD$)持续膨胀,不是临时 spikes,而是每天稳定增长——这基本说明背后有自动任务在写入且未清理,不能靠加数据文件硬扛。
查清到底是哪个对象在涨:别只看 dba_segments
直接查 dba_segments 可能漏掉 LOB 段或分区子对象,尤其 WRI$_SQLSET_PLAN_LINES 这类表的主段是 SYS_LOB 开头的,真实大小藏在 LOB 段里。优先用 v$sysaux_occupants 快速定位功能模块:
- 执行
SELECT occupant_name, ROUND(space_usage_kbytes/1024/1024, 2) AS gb FROM v$sysaux_occupants WHERE space_usage_kbytes > 0 ORDER BY space_usage_kbytes DESC;—— 关注SM/ADVISOR(统计顾问)、AUDSYS(统一审计)、ASTS(SQL 调优集) - 若
SM/ADVISOR排第一,再查具体表:SELECT segment_name, bytes/1024/1024/1024 gb FROM dba_segments WHERE tablespace_name = 'SYSAUX' AND segment_name LIKE 'WRI$_%' ORDER BY bytes DESC; - RAC 环境下必须在所有实例上都跑一遍,
dba_segments视图默认只返回当前实例的数据,容易误判
停写源头比清数据更关键:关任务,不删表
单纯 TRUNCATE TABLE WRI$_ADV_OBJECTS 或 DELETE FROM AUD$ 只是治标——任务还在跑,一小时后又回满。必须先切断写入源:
- 对
WRI$_ADV_OBJECTS:执行EXEC dbms_stats.set_global_prefs('AUTO_STATS_ADVISOR_TASK', 'FALSE');—— 注意这是全局参数,CDB 和所有 PDB 都生效 - 对
WRI$_SQLSET_PLAN_LINES(19.7 ASTS 组件):运行EXEC DBMS_AUTO_SPM_EVOLVE_TASK.DISABLE;,再确认SELECT client_name, status FROM dba_autotask_client WHERE client_name = 'sql tuning advisor';返回DISABLED - 对传统审计
AUD$:先NOAUDIT ALL;,再检查audit_trail参数是否为DB或OS;如果是DB,且AUD$在 SYSTEM 里,必须迁移,不能只关参数
清理已有数据:TRUNCATE 优先于 DELETE,但得看表结构
TRUNCATE 快、不占 UNDO、不触发触发器,但部分系统表(如 AUD$)不支持直接 TRUNCATE,而 WRI$_* 表多数可以:
-
TRUNCATE TABLE SYS.WRI$_ADV_OBJECTS;—— 安全,Oracle 官方文档明确允许 -
TRUNCATE TABLE SYS.WRI$_SQLSET_PLAN_LINES;—— 19.7+ 支持,但需先禁用 ASTS 任务,否则下次启动又写入 -
AUD$不能TRUNCATE:必须用DBMS_AUDIT_MGMT.CLEAN_AUDIT_TRAIL或迁移后ALTER TABLE SYS.AUD$ MOVE TABLESPACE USERS; - 避免
DELETE FROM ... WHERE ...:这类语句在 SYSAUX 里会生成巨量 UNDO,可能卡死 MMON 进程,甚至引发 ORA-01555
RAC 环境下移动或清理必须所有实例 MOUNT 状态
像 ALTER TABLE SYS.AUD$ MOVE 或 TRUNCATE 某些核心系统表,在 RAC 中不是在线操作。Oracle 会强制要求所有实例处于 MOUNT 状态(即数据库已关闭,控制文件已加载),否则报 ORA-01157 或静默失败:
- 执行前确认:
SELECT instance_name, status FROM gv$instance;—— 所有实例必须是MOUNTED - 不能只在一个节点执行,也不能用
srvctl stop instance停单个实例了事;必须srvctl stop database -d <db_name></db_name>全停 - 操作完成后,用
srvctl start database启动,不要只启一个实例 - 迁移
AUD$后记得重建索引:ALTER INDEX SYS.I_AUD1 REBUILD TABLESPACE USERS;,否则后续审计写入仍可能失败
真正麻烦的从来不是“怎么删”,而是“删完谁还在写”。盯住 v$sysaux_occupants 的 occupant_name,对应到具体自动任务,关掉它,再清理残留——这个顺序反了,等于给排水口塞抹布还指望水位下降。


















