根本原因是非标准对象堆积:应用用户对象误建、pl/sql编译残留(idl_ub1$等)或awr/统计信息错误写入system;须先用dba_segments定位owner和segment_type,再分类型处理,禁用直接truncate sys.aud$。

SYSTEM 表空间在 Oracle 12c 中占用过大,**根本原因不是“数据库变老了”,而是某些系统组件默认写入 SYSTEM 或因配置/误操作导致对象持续堆积**。直接扩容或盲目 TRUNCATE 可能引发 ORA-00604、ORA-01422 甚至实例无法启动。必须先定位真实来源,再分类型处理。
查清谁在占空间:聚焦 owner 和 segment_type
别只看 AUD$ —— 12c 默认审计已迁至 AUDSYS.AUD$UNIFIED(存于 SYSAUX),SYSTEM 里真正危险的是“非标准对象”。执行这句:
SELECT owner, segment_name, segment_type, ROUND(bytes/1024/1024) mb
FROM dba_segments
WHERE tablespace_name = 'SYSTEM'
AND owner NOT IN ('SYS','SYSTEM','XDB','ORDSYS','MDSYS','CTXSYS','DMSYS','WKSYS','WMSYS')
ORDER BY mb DESC;
关键判断点:
- 若
OWNER是应用用户(如SCOTT、APP_USER),说明该用户DEFAULT TABLESPACE被设为SYSTEM,或建表时漏写TABLESPACE子句 —— 这是管理事故,必须立刻修正; - 若
SEGMENT_NAME是IDL_UB1$、SOURCE$、IDL_UB2$,说明 PL/SQL 编译频繁或物化视图刷新异常,需清理 DIANA 缓存而非删表; - 若出现
WRH$或WRI$_OPTSTAT开头的对象,说明 AWR 或统计信息历史被错误写入SYSTEM(正常应在SYSAUX),需检查dbms_stats配置或 AWR 快照策略。
审计相关对象:12c 不要碰 SYS.AUD$
Oracle 12c 启用统一审计(Unified Audit)后,SYS.AUD$ 已废弃,仅作兼容保留。即使它还存在且占空间,TRUNCATE TABLE SYS.AUD$ 在 12c+ 会失败或触发内部一致性校验报错。
正确做法:
- 确认当前审计模式:
SELECT value FROM v$parameter WHERE name = 'audit_trail';—— 若返回UNIFIED_AUDIT_TRAIL,则实际审计数据在AUDSYS.AUD$UNIFIED,应清理该表(需AUDIT_ADMIN权限); - 若仍为
DB,说明未启用统一审计,但 12c 默认不推荐回退,应迁移至统一审计并清理旧AUD$:先执行EXEC DBMS_AUDIT_MGMT.CLEAN_AUDIT_TRAIL(audit_trail_type => DBMS_AUDIT_MGMT.AUDIT_TRAIL_DB, use_last_arch_timestamp => FALSE);,再调用DBMS_AUDIT_MGMT.FLUSH_UNIFIED_AUDIT_TRAIL; - 切勿手工
DROP或MOVEAUD$—— 它受 Oracle 内部字典保护,破坏后可能无法重建数据字典。
PL/SQL 编译残留:IDL_UB1$ 等表不能删,但可收缩
IDL_UB1$、SOURCE$ 是存储 PL/SQL 编译中间表示(DIANA)的系统表,增长主因是频繁编译大包、物化视图自动刷新触发重编译、或存在无效但未删除的旧版本对象。
监控 Victron Energy 电力系统,生成包含电池状态、光伏发电量和活动警报的精美每日邮件报告。集成 Vic...
安全清理方式:
- 先清理无效对象:
SELECT object_name, object_type FROM dba_objects WHERE status = 'INVALID' AND owner = 'SYS' AND created —— 对结果中确认无业务依赖的,用 <code>ALTER PACKAGE xxx COMPILE尝试修复,失败则DROP; - 收缩
IDL_UB1$:运行EXEC DBMS_UTILITY.RECOMP_ALL('SYS');强制重编译所有有效对象,触发 Oracle 自动清理过期 DIANA 条目; - 禁止在生产环境反复
CREATE OR REPLACE PACKAGE大型包 —— 每次编译都会在IDL_UB1$留下新版本,旧版本仅靠自动清理不一定及时释放。
迁移用户对象:唯一安全的“清理”动作
对 OWNER NOT IN ('SYS','SYSTEM',...) 的表、索引等,唯一合规操作是在线迁移出 SYSTEM,而不是删除或截断。
步骤:
- 为该用户创建专用表空间(如
USERS或APP_DATA); - 修改用户默认表空间:
ALTER USER app_user DEFAULT TABLESPACE users;; - 迁移现有段:
ALTER TABLE app_user.t1 MOVE TABLESPACE users;(堆表)、ALTER INDEX app_user.idx1 REBUILD TABLESPACE users;(索引); - 注意:迁移前确保目标表空间有足够空间,且
app_user对其有QUOTA;迁移大对象时建议在低峰期执行,并监控 undo 表空间使用。
最易被忽略的一点:SYSTEM 表空间里的对象,哪怕只占几 MB,只要 OWNER 不是 Oracle 内部账户,就代表数据库治理失控 —— 清理动作本身只是补救,建立部署规范(如所有 DDL 必须显式指定 TABLESPACE)才是根治。










