安全清理Oracle审计日志需分治AUD$表与.aud文件:AUD$须用DBMS_SCHEDULER分批(ROWNUM
oracle数据库里用存储过程自动清理日志,核心是两件事:明确日志存哪儿、选对清理时机。直接上结论——aud$表(audit_trail=db时)和操作系统级.aud文件必须分开处理,混用delete或rm会漏数据甚至破坏连接。
怎么写一个安全的AUD$清理存储过程
清理SYS.AUD$不能简单写DELETE FROM SYS.AUD$ WHERE ...就完事。这张表默认在SYSTEM表空间,大删容易锁表、阻塞审计写入,还可能触发ORA-01562(无法扩展回滚段)。
- 必须用
DBMS_SCHEDULER而不是过时的DBMS_JOB,后者在12c+已标记为deprecated - 删除语句要加
AND ROWNUM 分批执行,避免单次事务过大 - 执行前检查
SELECT COUNT(*) FROM SYS.AUD$ WHERE TIMESTAMP ,空结果直接退出,省得调度空跑 - 示例片段:
CREATE OR REPLACE PROCEDURE clean_audit_log_30days AS v_cnt NUMBER; BEGIN SELECT COUNT(*) INTO v_cnt FROM SYS.AUD$ WHERE TIMESTAMP LOOP DELETE FROM SYS.AUD$ WHERE TIMESTAMP
为什么不能只靠存储过程清理所有日志
存储过程管不了操作系统层的.aud文件。这些文件在$ORACLE_BASE/admin/$ORACLE_SID/adump/下,由Oracle进程直接写入,数据库内无法访问路径。硬要在存储过程中调用UTL_FILE去删?权限极难配,且adump目录被删空会导致sqlplus / as sysdba直接报ORA-01031,连不上库。
- 必须用操作系统级定时任务(如
crontab)配合find命令清理.aud - 关键参数:
-mtime +30比-ctime更可靠,它按文件内容修改时间算,不受touch误操作干扰 - 绝对禁止
rm -rf $ORACLE_BASE/admin/$ORACLE_SID/adump/,只删文件不删目录 - 清理后建议
ls -lt $ORACLE_BASE/admin/$ORACLE_SID/adump/ | head -5快速验证最新文件时间戳
RMAN清理归档日志要不要走存储过程
不要。RMAN本身不是SQL引擎,DELETE ARCHIVELOG这类命令必须在RMAN客户端上下文里执行,没法塞进PL/SQL块。强行用DBMS_SCHEDULER调外部脚本(如rman target / @clean_arch.rman)风险更高——RMAN连接失败时错误不透出,日志里只显示“job completed”,实际什么都没删。
- 归档日志清理必须用独立RMAN脚本+
crontab组合 - 关键命令用
DELETE NOPROMPT ARCHIVELOG ALL COMPLETED BEFORE 'SYSDATE-1',NOPROMPT防交互卡住 - 执行前务必加
CROSSCHECK ARCHIVELOG ALL,否则RMAN可能删错(比如闪回区还在用的归档) - 多节点RAC环境,每个节点都要部署相同crontab,别指望一个节点代劳
最容易被忽略的是AUD$表的SHRINK SPACE——删完数据只是逻辑删除,高水位线(HWM)没降,表空间不会释放。必须在存储过程末尾加ALTER TABLE SYS.AUD$ SHRINK SPACE CASCADE,且确保SYSTEM表空间启用了段空间管理(SEGMENT_SPACE_MANAGEMENT=AUTO),否则SHRINK直接报ORA-10636。











