پیاده‌سازی Retention هفت‌روزه برای Unified Auditing در Oracle 19c (CDB/PDB)

مقدمه

در دیتابیس‌های 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 گاهی باعث خطای زیر می‌شود:

 
PLS-00306: wrong number or types of arguments
 
راه‌حل مطمئن: استفاده از positional 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:

  1. SET_LAST_ARCHIVE_TIMESTAMP فقط مرز را تعیین می‌کند

  2. CREATE_PURGE_JOB تنها جایی است که واقعاً پاک می‌کند

  3. برای Retention شناور، job جداگانه برای به‌روزرسانی timestamp ضروری است

  4. خالی شدن PDB بعد از purge لزوماً خطا نیست

  5. استفاده از positional arguments در SQL*Plus بسیار پایدارتر است