مقدمه
در دیتابیسهای Oracle که Unified Auditing فعال است، حجم دادههای audit میتواند بهسرعت رشد کند.
Oracle برای مدیریت این دادهها پکیجی به نام DBMS_AUDIT_MGMT ارائه داده، اما تجربهی عملی نشان میدهد که صرف ساختن purge job بهتنهایی برای پیادهسازی retention واقعی کافی نیست.
در این مقاله، بر اساس یک سناریوی واقعی در Oracle 19c، پیادهسازی Retention شناور (Rolling) هفتروزه برای Unified Audit Trail را از صفر تا صد بررسی میکنیم؛ شامل:
-
بررسی وضعیت اولیه CDB و PDB
-
تنظیم صحیح Last Archive Timestamp
-
ساخت Purge Job استاندارد
-
حل خطاهای رایج (PLS-00306)
-
اثبات دقیق اینکه «پاکسازی» دقیقاً کِی و توسط کدام job انجام میشود
مشخصات محیط
-
Oracle Database 19c
-
معماری: CDB + PDB
-
PDB مورد بررسی:
VAHIDPDB -
Unified Auditing فعال
مرحله 1: بررسی ساختار دیتابیس
show con_name;
show pdbs;
خروجی:
CON_NAME
------------------------------
CDB$ROOT
CON_ID CON_NAME OPEN MODE
------ --------- ----------
2 PDB$SEED READ ONLY
3 VAHIDPDB READ WRITE
مرحله 2: بررسی وضعیت Unified Audit Trail قبل از هر تغییری
در CDB$ROOT
alter session set container=CDB$ROOT;
select count(*) as total_cnt
from unified_audit_trail;
SELECT
SUM(CASE WHEN event_timestamp < (SYSTIMESTAMP - INTERVAL '7' DAY) THEN 1 ELSE 0 END) AS older_than_7d,
SUM(CASE WHEN event_timestamp >= (SYSTIMESTAMP - INTERVAL '7' DAY) THEN 1 ELSE 0 END) AS last_7d
FROM unified_audit_trail;
select min(event_timestamp) as min_ts,
max(event_timestamp) as max_ts
from unified_audit_trail;
خروجی:
TOTAL_CNT
---------
15046
OLDER_THAN_7D LAST_7D
------------- -------
15044 2
MIN_TS MAX_TS
-------------------------------- --------------------------------
17-DEC-25 07:45:52 AM 30-JAN-26 09:58:39 AM
در PDB که دادهی واقعی داشت (VAHIDPDB)
alter session set container=VAHIDPDB;
select count(*) as total_cnt
from unified_audit_trail;
SELECT
SUM(CASE WHEN event_timestamp < (SYSTIMESTAMP - INTERVAL '7' DAY) THEN 1 ELSE 0 END) AS older_than_7d,
SUM(CASE WHEN event_timestamp >= (SYSTIMESTAMP - INTERVAL '7' DAY) THEN 1 ELSE 0 END) AS last_7d
FROM unified_audit_trail;
خروجی:
TOTAL_CNT
---------
11107
OLDER_THAN_7D LAST_7D
------------- -------
11102 5
مرحله 3: تنظیم معیار Retention (Last Archive Timestamp)
این مرحله فقط مرز پاکسازی را تعیین میکند، نه خود پاکسازی را.
قبل از تنظیم این جستجو را اجرا می کنیم تا ببینیم پیش از این تنظیمی برای این موضوع انجام شده است یا خیر:
select audit_trail, last_archive_ts
from dba_audit_mgmt_last_arch_ts
where audit_trail='UNIFIED AUDIT TRAIL';
در صورتی که نتیجه ای بر نگرداند، یعنی تنظیمی انجام نشده است.
alter session set container=CDB$ROOT;
BEGIN
DBMS_AUDIT_MGMT.SET_LAST_ARCHIVE_TIMESTAMP(
audit_trail_type => DBMS_AUDIT_MGMT.AUDIT_TRAIL_UNIFIED,
last_archive_time => CAST(
(SYSTIMESTAMP AT TIME ZONE 'UTC') - INTERVAL '7' DAY
AS TIMESTAMP
),
container => DBMS_AUDIT_MGMT.CONTAINER_ALL
);
END;
/
بررسی مقدار تنظیمشده:
select audit_trail, last_archive_ts
from dba_audit_mgmt_last_arch_ts
where audit_trail='UNIFIED AUDIT TRAIL';
خروجی:
AUDIT_TRAIL LAST_ARCHIVE_TS
-------------------- ---------------------------------------
UNIFIED AUDIT TRAIL 23-JAN-26 03:08:29 PM +00:00
مرحله 4: ساخت Purge Job (جایی که واقعاً پاکسازی انجام میشود)
نکته بسیار مهم
در SQL*Plus استفاده از named arguments گاهی باعث خطای زیر میشود:
set define off
set sqlblanklines on
BEGIN
AUDSYS.DBMS_AUDIT_MGMT.CREATE_PURGE_JOB(
AUDSYS.DBMS_AUDIT_MGMT.AUDIT_TRAIL_UNIFIED,
24,
'PURGE_UNIFIED_AUDIT_TRAIL',
TRUE,
AUDSYS.DBMS_AUDIT_MGMT.CONTAINER_ALL
);
END;
/
بررسی ایجاد job
select job_name, job_status, job_frequency,
use_last_archive_timestamp, job_container
from dba_audit_mgmt_cleanup_jobs
where job_name = 'PURGE_UNIFIED_AUDIT_TRAIL';
خروجی:
JOB_NAME PURGE_UNIFIED_AUDIT_TRAIL
JOB_STATUS ENABLED
JOB_FREQUENCY FREQ=HOURLY;INTERVAL=24
USE_LAST_ARCHIVE_TIMESTAMP YES
JOB_CONTAINER ALL
مرحله 5: اتوماتسازی Retention شناور (Rolling Window)
اگر LAST_ARCHIVE_TS بهروز نشود، retention ثابت میماند.
پس یک job سبک برای آپدیت روزانهی آن لازم است.
ساخت Procedure
CREATE OR REPLACE PROCEDURE sys.set_unified_last_arch_7d_all IS
BEGIN
AUDSYS.DBMS_AUDIT_MGMT.SET_LAST_ARCHIVE_TIMESTAMP(
audit_trail_type => AUDSYS.DBMS_AUDIT_MGMT.AUDIT_TRAIL_UNIFIED,
last_archive_time => CAST(
(SYSTIMESTAMP AT TIME ZONE 'UTC') - INTERVAL '7' DAY
AS TIMESTAMP
),
container => AUDSYS.DBMS_AUDIT_MGMT.CONTAINER_ALL
);
END;
/
ساخت Scheduler Job روزانه
BEGIN
DBMS_SCHEDULER.CREATE_JOB(
job_name => 'SYS.JOB_SET_UNIFIED_LAST_ARCH_7D_DAILY',
job_type => 'STORED_PROCEDURE',
job_action => 'SYS.SET_UNIFIED_LAST_ARCH_7D_ALL',
start_date => SYSTIMESTAMP,
repeat_interval => 'FREQ=DAILY;BYHOUR=1;BYMINUTE=0;BYSECOND=0',
enabled => TRUE
);
END;
/
مرحله 6: اثبات اینکه پاکسازی دقیقاً کِی انجام شده
select owner, job_name, last_start_date, next_run_date
from dba_scheduler_jobs
where job_name = 'PURGE_UNIFIED_AUDIT_TRAIL';
خروجی:
LAST_START_DATE
------------------------------
30-JAN-26 10:05:52 AM EST5EDT
select log_date, status
from dba_scheduler_job_run_details
where job_name='PURGE_UNIFIED_AUDIT_TRAIL'
order by log_date desc;
خروجی:
30-JAN-26 10:05:54 AM -05:00 SUCCEEDED
تیجه:
پاکسازی دقیقاً توسط PURGE_UNIFIED_AUDIT_TRAIL انجام شده است.
مرحله 7: وضعیت نهایی بعد از purge (در PDB)
alter session set container=VAHIDPDB;
SELECT
SUM(CASE WHEN event_timestamp < (SYSTIMESTAMP - INTERVAL '7' DAY) THEN 1 ELSE 0 END) AS older_than_7d,
SUM(CASE WHEN event_timestamp >= (SYSTIMESTAMP - INTERVAL '7' DAY) THEN 1 ELSE 0 END) AS last_7d
FROM unified_audit_trail;
خروجی:
OLDER_THAN_7D LAST_7D
------------- -------
0 5
برای پیادهسازی Retention واقعی هفتروزه در Unified Auditing:
-
SET_LAST_ARCHIVE_TIMESTAMPفقط مرز را تعیین میکند -
CREATE_PURGE_JOBتنها جایی است که واقعاً پاک میکند -
برای Retention شناور، job جداگانه برای بهروزرسانی timestamp ضروری است
-
خالی شدن PDB بعد از purge لزوماً خطا نیست
-
استفاده از positional arguments در SQL*Plus بسیار پایدارتر است