티스토리 뷰

개요

Oracle Database 12cR2 이후로 DBMS_JOB 패키지는 더 이상 사용되지 않으며, Oracle 19c에서는 DBMS_JOB으로 생성된 모든 작업이 자동으로 DBMS_SCHEDULER 작업으로 변환됩니다. 이 문서에서는 이러한 변화에 대한 개요와 주요 사항을 정리합니다.


DBMS_JOB을 사용한 작업 생성

1. 기존 작업 조회

conn test/test@pdb1
column what format a30
select job, what from user_jobs;

출력 결과:

0 rows selected.

2. DBMS_JOB을 이용한 작업 생성

declare
  l_job  pls_integer;
begin
  dbms_job.submit (
    job       => l_job,
    what      => 'begin null; end;',
    next_date => trunc(sysdate)+1,
    interval  => 'trunc(sysdate)+1'
  );
end;
/

3. 생성된 작업 조회

select job, what from user_jobs;

출력 결과:

JOB   WHAT
----  ------------------------------
  1   begin null; end;
select job_name, job_action from user_scheduler_jobs;

출력 결과:

JOB_NAME       JOB_ACTION
-------------- ------------------------------
DBMS_JOB$_1    begin null; end;

트랜잭션 작업 (Transactional Jobs)

DBMS_JOB을 이용하면 트랜잭션 내에서 작업을 생성하고 롤백할 수 있습니다. DBMS_SCHEDULER로 변환된 작업도 동일한 방식으로 작동합니다.

1. 새로운 Session에서 작업 조회

conn test/test@pdb1
select job, what from user_jobs;

출력 결과:

0 rows selected.

2. 기존 Session에서 Rollback 후 작업 조회

rollback;
select job, what from user_jobs;

출력 결과:

0 rows selected.

Materialized View Refresh Groups

Oracle 19c에서는 DBMS_JOB을 사용하여 구현되던 Materialized View Refresh Groups이 DBMS_SCHEDULER를 사용하여 처리됩니다.

1. Table 및 Materialized View 생성

create table t1 (id number);
create materialized view t1_mv
refresh force
on demand
as
select * from t1;

2. Refresh Group 생성

begin
   dbms_refresh.make(
     name => 'MINUTE_REFRESH',
     next_date => sysdate,
     interval  => 'sysdate + 1/(60*24)',
     job => 0);
end;
/

3. 작업 조회

select job_name, job_action from user_scheduler_jobs;

출력 결과:

JOB_NAME         JOB_ACTION
---------------- ------------------------------
MV_RF$J_0_S_210 dbms_refresh.refresh('"TEST"."MINUTE_REFRESH"');

4. Rollback 후 작업 조회

rollback;
select job_name, job_action from user_scheduler_jobs;

출력 결과:

0 rows selected.

보안 문제: CREATE JOB 권한 필요

Oracle 19c에서는 DBMS_JOB을 사용하여 작업을 생성하려면 CREATE JOB 권한이 필요합니다.

1. 권한 없이 작업 생성 시도

create user test2 identified by test2;
grant create session to test2;
conn test2/test2@pdb1

declare
  l_job  pls_integer;
begin
  dbms_job.submit (
    job       => l_job,
    what      => 'begin null; end;',
    next_date => trunc(sysdate)+1,
    interval  => 'trunc(sysdate)+1'
  );
end;
/

출력 결과:

ORA-27486: insufficient privileges

2. Refresh Group을 이용한 우회 방법

begin
   dbms_refresh.make(
     name => 'MINUTE_REFRESH',
     next_date => sysdate,
     interval  => 'sysdate + 1/(60*24)',
     job => 0);
end;
/

select job_name, job_action from user_scheduler_jobs;

출력 결과:

JOB_NAME         JOB_ACTION
---------------- ------------------------------
MV_RF$J_0_S_242 dbms_refresh.refresh('"TEST2"."MINUTE_REFRESH"');

3. 작업 속성 변경

begin
  dbms_scheduler.set_attribute (
    name      => 'MV_RF$J_0_S_242',
    attribute => 'job_action',
    value     => 'begin null; end;'
  );
end;
/

DBMS_REFRESH 패키지를 통해 권한 없이 작업을 생성할 수 있는 보안 문제가 있으며, 이를 해결하기 위해 DBMS_REFRESH 패키지에 대한 EXECUTE 권한을 PUBLIC에서 제거하는 것이 권장됩니다.


기타 사항

  • CREATE JOB 권한이 없으면 DBMS_JOB을 사용할 수 없습니다.
  • 19c 업그레이드 시 기존 DBMS_JOB 작업은 자동으로 DBMS_SCHEDULER로 변환됩니다.
  • SCHEDULER$_DBMSJOB_MAP 뷰에서 변환된 작업을 확인할 수 있습니다.
SQL> desc scheduler$_dbmsjob_map;
Name            Null?    Type
--------------- -------- -------------
DBMS_JOB_NUMBER NOT NULL NUMBER
JOB_OWNER       NOT NULL VARCHAR2(128)
JOB_NAME        NOT NULL VARCHAR2(128)

결론

Oracle 19c에서는 DBMS_JOB 패키지가 더 이상 권장되지 않으며, 모든 작업이 DBMS_SCHEDULER로 변환됩니다. 트랜잭션을 유지하는 기능은 제공되지만, 보안 정책이 변경되었으므로 이에 대한 대비가 필요합니다. 또한, DBMS_REFRESH를 이용한 보안 우회 가능성이 있으므로 주의가 필요합니다.

 

참고 자료