必须用dbms_audit_mgmt清理sys.aud$,因其为受保护系统表,直接delete或truncate会报ora-00942或ora-01031错误,且破坏审计一致性;清理后需手动shrink space或move段释放空间。

sys.aud$ 表清理必须用 DBMS_AUDIT_MGMT,不能直接 DELETE
Oracle 审计表 sys.aud$ 是系统级表,位于 SYSTEM 或 SYSAUX 表空间,普通用户甚至 DBA 都无法直接对它执行 DELETE 或 TRUNCATE —— 会报 ORA-00942: table or view does not exist 或权限拒绝。官方唯一支持的清理方式是调用 DBMS_AUDIT_MGMT 包,否则可能破坏审计一致性或引发 ORA-600 错误。
常见错误现象:
- 用
DELETE FROM sys.aud$ WHERE ntimestamp# 报错退出 - 误删后发现
SELECT * FROM DBA_AUDIT_TRAIL查询变慢或缺失历史记录 - 手动
TRUNCATE TABLE sys.aud$导致后续审计开关失败(audit_trail参数失效)
实操要点:
- 必须用
SYS用户登录执行,且需具备EXECUTE_CATALOG_ROLE权限 - 清理前先确认归档时间戳:
SELECT * FROM dba_audit_mgmt_last_arch_ts,只允许删「已归档」的数据 - 首次使用前必须运行
init_cleanup初始化,否则clean_audit_trail会静默失败
清理前务必设置 last_archive_timestamp,否则 clean_audit_trail 不生效
DBMS_AUDIT_MGMT.clean_audit_trail 不接受日期参数,它只按 last_archive_time 标记来判断哪些数据可删。这个标记是独立于物理数据的逻辑开关,不设就等于“没授权删任何数据”,命令会跑完但 sys.aud$ 行数纹丝不动。
典型误操作:
- 跳过
set_last_archive_timestamp直接跑clean_audit_trail,日志显示成功,实际零删除 - 传入的时间早于
dba_audit_mgmt_last_arch_ts中记录的归档时间,触发 ORA-46275 错误 - 用
SYSDATE - 7但未考虑时区,导致跨天偏差(尤其在 RAC 环境中)
正确写法(清理 7 天前已归档数据):
BEGIN
sys.DBMS_AUDIT_MGMT.set_last_archive_timestamp(
audit_trail_type => sys.DBMS_AUDIT_MGMT.AUDIT_TRAIL_AUD_STD,
last_archive_time => SYSTIMESTAMP - 7
);
END;
注意:SYSTIMESTAMP 比 SYSDATE 更可靠,它带时区信息,避免跨节点时间漂移。
清理后空间不释放?要手动 shrink 或 move segment
clean_audit_trail 只是逻辑删除:把行标记为“可覆盖”,并不回收磁盘空间。你执行完后查 dba_segments,AUD$ 的 BYTES 值几乎不变,SYSAUX 表空间使用率也不会降——这是正常行为,不是清理失败。
释放空间必须额外两步:
- 如果是非 RAC 单实例,且
AUD$在SYSAUX中,运行ALTER TABLE sys.aud$ SHRINK SPACE CASCADE(需表启用行移动) - 更稳妥的做法是
ALTER TABLE sys.aud$ MOVE TABLESPACE sysaux,强制重建段并压缩空块 - 若表空间快满,可先
ALTER DATABASE DATAFILE '...sysaux01.dbf' AUTOEXTEND OFF防止写满宕机
风险提示:MOVE 操作期间审计功能仍可用,但会短暂阻塞新审计记录写入(通常
自动化清理脚本必须加熔断和校验,别信“一次配好永不动”
生产环境曾有案例:定时任务每小时调用 clean_audit_trail,但某次归档时间戳被误设为 SYSTIMESTAMP - 30,结果连续删掉近一个月审计数据,导致安全合规审计失败。
防误删关键措施:
- 脚本开头加校验:
SELECT COUNT(*) FROM sys.aud$ WHERE ntimestamp# ,若结果 > 100 万行,自动暂停并发邮件告警 - 每次清理后执行
ANALYZE TABLE sys.aud$ COMPUTE STATISTICS,防止后续查询因统计信息陈旧而走全表扫描 - 硬编码保留底线,例如在
set_last_archive_timestamp中写死last_archive_time => GREATEST(SYSTIMESTAMP - 7, DATE '2025-01-01')
最易被忽略的一点:DBMS_AUDIT_MGMT 的清理是异步的,命令返回成功 ≠ 数据已删完。真正完成要看后台进程 ora_q00x_* 的日志,高峰期可能延迟数分钟。











