Oracle如何遷移、管理、清除Audit數據(AUD$和FGA_LOG$表)
前言
版本:11.2.0.4.0。
Oracle 11G中沒特殊要求還是要建議關閉審計功能:alter system set audit_trail = none scope=spfile sid='*';
由於默認審計數據的AUD$和FGA_LOG$表在system表空間,在開啟審計情況下,可能會導致AUD$表體積巨大導致system表空間不足。
如果不關閉審計,則建議將這兩張表遷移至其他表空間。
如何遷移
在不關閉審計情況下,建議遷移AUD$和FGA_LOG$,根據How To Move The DB Audit Trails To A New Tablespace Using DBMS_AUDIT_MGMT? (Doc ID 1328239.1),有(示例):
表空間: SELECT table_name, tablespace_name FROM dba_tables WHERE table_name IN ('AUD$', 'FGA_LOG$') ORDER BY table_name; TABLE_NAME TABLESPACE_NAME ------------------------------ ------------------------------ AUD$ SYSTEM FGA_LOG$ SYSTEM 段大小: col segment_name for a25 set linesize 500 select segment_name,bytes/1024/1024 size_in_megabytes from dba_segments where segment_name in ('AUD$','FGA_LOG$'); SEGMENT_NAME SIZE_IN_MEGABYTES ------------------------- ----------------- FGA_LOG$ .0625 AUD$ 4448
創建新的表空間用來存放AUD$以及FGA_LOG$表:
create tablespace audit_tbs datafile '+DATA' size 6G autoextend off uniform size 1M;
然后再移動表即可:
BEGIN DBMS_AUDIT_MGMT.set_audit_trail_location( audit_trail_type => DBMS_AUDIT_MGMT.AUDIT_TRAIL_AUD_STD,--this moves table AUD$ audit_trail_location_value => 'AUDIT_TBS'); END; / BEGIN DBMS_AUDIT_MGMT.set_audit_trail_location( audit_trail_type => DBMS_AUDIT_MGMT.AUDIT_TRAIL_FGA_STD,--this moves table FGA_LOG$ audit_trail_location_value => 'AUDIT_TBS'); END; / SELECT table_name, tablespace_name FROM dba_tables WHERE table_name IN ('AUD$', 'FGA_LOG$') ORDER BY table_name;
備份
通過數據泵expdp來導出實現備份。
或者通過create table 用戶.表名 tablespace 表空間 as select * from aud$ where ....
如何管理/清除
在不關閉審計情況下,建議定期對AUD$表做備份清理的動作,控制AUD$表體積。
發現有的第三方審計安全軟件會對AUD$做讀取操作(只能是全表,AUD$表沒有索引(The Effect Of Creating Index On Table Sys.Aud$ (Doc ID 1329731.1)))。
Oracle建議使用dbms_audit_mgmt來管理AUD$表,這個包還能用來定制清理策略、清理數據等。
根據SCRIPT: Basic example to manage AUD$ table with dbms_audit_mgmt (Doc ID 1362997.1),有
如下(將腳本的內容復制到文件中,對其進行自定義並以sysdba身份運行。):
-- Example re-locating AUD$ and setting up a purge job set serveroutput on prompt First Step: init cleanup (if not already) BEGIN IF NOT DBMS_AUDIT_MGMT.IS_CLEANUP_INITIALIZED(DBMS_AUDIT_MGMT.AUDIT_TRAIL_AUD_STD) THEN dbms_output.put_line('Calling DBMS_AUDIT_MGMT.INIT_CLEANUP'); DBMS_AUDIT_MGMT.INIT_CLEANUP(audit_trail_type => dbms_audit_mgmt.AUDIT_TRAIL_AUD_STD, default_cleanup_interval => 24 * 7); else dbms_output.put_line('Cleanup for STD was already initialized'); end if; end; / prompt Relocate AUD$ to a dedicated tablespace AUDIT_DATA begin DBMS_AUDIT_MGMT.SET_AUDIT_TRAIL_LOCATION(audit_trail_type => dbms_audit_mgmt.AUDIT_TRAIL_AUD_STD, audit_trail_location_value => 'AUDIT_DATA'); end; / prompt set last archive timestamp to a week before now begin DBMS_AUDIT_MGMT.SET_LAST_ARCHIVE_TIMESTAMP(audit_trail_type => DBMS_AUDIT_MGMT.AUDIT_TRAIL_AUD_STD, last_archive_time => sysdate - 7); end; / prompt setup a purge job BEGIN DBMS_AUDIT_MGMT.DROP_PURGE_JOB(AUDIT_TRAIL_PURGE_NAME => 'Standard_Audit_Trail_PJ'); -- exception -- when others then -- null; end; / BEGIN DBMS_AUDIT_MGMT.CREATE_PURGE_JOB(AUDIT_TRAIL_TYPE => DBMS_AUDIT_MGMT.AUDIT_TRAIL_AUD_STD, AUDIT_TRAIL_PURGE_INTERVAL => 24, AUDIT_TRAIL_PURGE_NAME => 'Standard_Audit_Trail_PJ', USE_LAST_ARCH_TIMESTAMP => TRUE); END; / prompt Stop here if you use Audit Vault, otherwise press Enter pause prompt call DBMS_AUDIT_MGMT.SET_LAST_ARCHIVE_TIMESTAMP regularly to advance prompt the last archive ts, Audit Vault will do this for you automatically prompt Optionally Schedule automatic advancement of the archive timestamp create or replace procedure set_archive_retention(retention in number default 7) as begin DBMS_AUDIT_MGMT.SET_LAST_ARCHIVE_TIMESTAMP(audit_trail_type => DBMS_AUDIT_MGMT.AUDIT_TRAIL_AUD_STD, last_archive_time => sysdate - retention); end; / begin DBMS_SCHEDULER.disable('advance_archive_timestamp'); DBMS_SCHEDULER.drop_job('advance_archive_timestamp'); -- exception -- when others then -- null; end; / BEGIN DBMS_SCHEDULER.create_job(job_name => 'advance_archive_timestamp', job_type => 'STORED_PROCEDURE', job_action => 'SET_ARCHIVE_RETENTION', number_of_arguments => 1, start_date => SYSDATE, repeat_interval => 'freq=daily', enabled => false, auto_drop => FALSE); dbms_scheduler.set_job_argument_value(job_name => 'advance_archive_timestamp', argument_position => 1, -- one week, you can customize this line: argument_value => 7); DBMS_SCHEDULER.ENABLE('advance_archive_timestamp'); End; / BEGIN DBMS_SCHEDULER.run_job(job_name => 'advance_archive_timestamp', use_current_session => FALSE); END; / -- end example
以上腳本通過自定義job來定期清理7天前的數據,可以訪問清理Audit數據幫助理解各個步驟的意思。
也可以手工清理數據:
set serveroutput on prompt First Step: init cleanup (if not already) BEGIN IF NOT DBMS_AUDIT_MGMT.IS_CLEANUP_INITIALIZED(DBMS_AUDIT_MGMT.AUDIT_TRAIL_AUD_STD) THEN dbms_output.put_line('Calling DBMS_AUDIT_MGMT.INIT_CLEANUP'); DBMS_AUDIT_MGMT.INIT_CLEANUP(audit_trail_type => dbms_audit_mgmt.AUDIT_TRAIL_AUD_STD, default_cleanup_interval => 24 * 7); else dbms_output.put_line('Cleanup for STD was already initialized'); end if; end; / begin DBMS_AUDIT_MGMT.SET_LAST_ARCHIVE_TIMESTAMP(audit_trail_type => DBMS_AUDIT_MGMT.AUDIT_TRAIL_AUD_STD, last_archive_time => sysdate - 7); end; / BEGIN sys.DBMS_AUDIT_MGMT.clean_audit_trail(audit_trail_type => sys.DBMS_AUDIT_MGMT.AUDIT_TRAIL_AUD_STD, use_last_arch_timestamp => TRUE); END; /
我遇到的問題是審計是關閉的,但是由於關閉之前AUD$以及達到了7個多G的數據,使用上邊手工清理語句,在執行斜體部分進行清理的時候清理時間達到了2個多小時,
並且高水位線並沒有被回收,即select aud$表雖然記錄為0但是依舊會訪問7個多G的物理讀(direct path read),需要再次通過如下動作回收高水位線:
11:41:52 SYS@xxxxxxx1(217)> select count(*) from AUD$; COUNT(*) ---------- 0 Elapsed: 00:00:20.40 14:17:08 SYS@xxxxxxx1(2211)> col SEGMENT_NAME for a35 14:21:08 SYS@xxxxxxx1(2211)> select segment_name,bytes/1024/1024 from dba_segments where segment_name='AUD$'; SEGMENT_NAME BYTES/1024/1024 ----------------------------------- --------------- AUD$ 7632 Elapsed: 00:00:00.03 14:21:12 SYS@xxxxxxx1(2211)> alter table sys.aud$ enable row movement; Table altered. Elapsed: 00:00:00.26 14:21:27 SYS@xxxxxxx1(2211)> alter table sys.aud$ shrink space cascade; Table altered. Elapsed: 00:11:05.15 14:35:42 SYS@xxxxxxx1(2211)> alter table sys.aud$ disable row movement; Table altered. Elapsed: 00:00:00.07 14:36:18 SYS@xxxxxxx1(2211)> select segment_name,bytes/1024/1024 from dba_segments where segment_name='AUD$'; SEGMENT_NAME BYTES/1024/1024 ----------------------------------- --------------- AUD$ 1 Elapsed: 00:00:00.02
Oracle雖然說盡量避免對AUD$做truncate操作,但是根據我網上查找資料,還是可以truncate的沒問題。
至於FGA_LOG$表,How to cleanup the log table FGA_LOG$ ? (Doc ID 402528.1)表明可以直接delete或者truncate沒問題,如下:
The FGA_LOG$ table can be deleted from or truncated to manage its space, for example: SQL> connect / as sysdba Connected. SQL> truncate table fga_log$; Table truncated. Alternatively you can delete records based on the TIMESTAMP# (date) column as follows: SQL> delete from fga_log$ where timestamp# < sysdate-14; This deletes all rows older than 2 weeks. Cleaning up the records in FGA_LOG$ is much like cleaning up audit records for standard auditing in table SYS.AUD$ .
至此。
