IT기술/Oracle

11 DBMS_JOB & DBMS_SCHEDULER

dobbby 2013. 12. 10. 17:36
반응형

1. DBMS_JOB 패키지 살펴보기

job_queue_process = 1     SNP 프로세스의 개수를 지정

job_queue_interval = 60     SNP 프로세스가 sleep 상태에서 깨어나는 간격을 초로 지정


submit         새로운 작업을 job queue 목록에 등록

remove        job queue 에 등록된 job 을 제거

change        job queue 에 등록된 job 을 변경

next_date     작동 시간 변경

interval        수행주기 변경

what            수행할 procedure or package 변경

run                등록되어 있는 특정 job 을 수동으로 수행


1) job 관리하기

기본 문법

DBMS_JOB.submit (

job out binary_integer,

what in varchar2,

next_date in date default sysdate,

interval in varchar2 default 'null',

no_parse in boolean default false

)


주요 파라미터의 의미

job               job 번호로 다른 프로시저에서 호출될 수 도 있다.

what            수행할 pl/sql or procedure or package  이름을 지정

이 곳에 직접 수행하기를 원하는 sql 문장을 써도 된다.

next_date      다음에 수행될 시간을 지정한다

interval         수행되는 주기를 지정하며 초 단위까지 지정 가능

no_parse       parse 여부 지정, 기본값은 false 로 parse 를 수행


(1) 새로운 job 등록 테스트 하기

step1 테스트용 테이블과 sequence, procedure 생성


SYS>conn scott/tiger

Connected.

SCOTT>

SCOTT>

SCOTT>create sequence seq_job_seq1 ;


Sequence created.


SCOTT>create table job_test01

  2  (no number,

  3  name varchar2(5));


Table created.


SCOTT>create or replace procedure insert_job_test01

  2  is

  3  begin

  4  insert into scott.job_test01

  5  values(seq_job_seq1.nextval, dbms_random.string('a',3)) ;

  6  end ;

  7  /




step2 job 을 등록할 프로시저를 생성한다


SCOTT>!vi job1.sql

begin

dbms_job.submit (:jno,

'scott.insert_job_test01;',

sysdate,

'sysdate + 1/24/60',        -- 1분에 한번씩 실행

false);

end;

/



시간 설정 방법
10분에 한번씩 실행
sysdate + 1/24/6 또는 sysdate + 1/144
1/24 (1시간 - 60분) / 6 : 10분 단위, 1/144 : 24*6 으로 나누어도 같은 의미
(1일은 1440 분이므로)

1분에 한번으로 지정하는 경우
sysdate + 1/24/60 또는 sysdate + 1/1440

5분에 한번
sysdate + 5/24/60

매일 새벽 2시
trunc(sysdate) + 1 + 2/24     다음날 새벽 2시를 지정
trunc 함수를 사용하지 않을경우 분:초단위까지 나오게 된다

매일 밤 11시
trunc(sysdate) + 23/24         오늘 밤 11시

step3 job을 등록
SCOTT>variable jno number ;
SCOTT>
SCOTT>@job1.sql

PL/SQL procedure successfully completed.

SCOTT>print jno ;

       JNO
----------
         4

SCOTT>commit ;

Commit complete.




step4. 수행되고 있는 job 내역을 확인한다

  1  select what, job, next_date, next_sec, failures, broken
  2  from user_jobs
  3* where what = 'scott.insert_job_test01;'



step5 실제 테이블에 데이터가 입력되는지 확인한다.

SCOTT>select * from job_test01 ;



(2) 등록되어 있는 job 삭제하기

SCOTT>exec dbms_job.remove(3) ;

PL/SQL procedure successfully completed.

SCOTT>exec dbms_job.remove(4) ;

PL/SQL procedure successfully completed.

SCOTT>select what, job, next_date, next_sec, failures, broken
  2  from user_jobs
  3  where job = 25 ;




(3) 등록되어 있는 job 수정하기

SCOTT>variable jno number ;
SCOTT>@job1.sql

PL/SQL procedure successfully completed.

SCOTT>print jno ;

       JNO
----------
         5

SCOTT>
SCOTT>
SCOTT>commit ;

Commit complete.

SCOTT> select what, job, next_date, next_sec, interval
  2  from user_jobs
  3* where job = 5



SCOTT>exec dbms_job.change(:jno, 'scott.insert_job_test01;', sysdate, 'sysdate + 5/24/60') ;

PL/SQL procedure successfully completed.

SCOTT>set line 200
SCOTT>col interval for a30
SCOTT>select what, job, next_date, next_sec, interval
  2  from user_jobs
  3  where job = 5 ;




2. DBMS_SCHEDULER (10g 이상 사용 가능) 

DBMS_JOB 에서는 안되는 외부 스크립트를 실행할 수 있다.

(1) 주요 특징
1) os 생성된 각종 유틸이나 프로그램까지도 실행할 수 있다.
2) 다양한 설정으로 일반적으로 사용하는 자연어를 사용하여 편하게 설정할 수 있다.
3) 데이터베이스 내부 이벤트까지 추적가능하기 때문에 os 나 dbms_job 보다 훨씬 다양하게 작업을 체크하고 수행할 수 있다.

(2) 구성
1) program
이 부분에 dbms_scheduler 가 수행할 프로그램이나 프로시저, 스크립트 등에 대한 정보를 저장해서 별도로 생성할 수 있다.

2) schedule
이 부분에 dbms_scheduler 가 수행할 job 이 실제 수행할 시간이나 실행 주기 등을 별도로 생성할 수 있다.

3) job
새로 생성할 dbms_scheduler 가 수행할 job 이 실제 수행할 시간이나 실행주기 등을 별도로 생성할 수 있다.

(3) DBMS_SCHEDULER 사용하기
1) 신규 job 생성하기

SYS>grant create any job to scott ;

Grant succeeded.

SYS>conn scott/tiger ;
Connected.
SCOTT>
SCOTT>create table job_test1
  2  (no number,
  3  name varchar2(5),
  4  rdate date default sysdate) ;

Table created.

SCOTT>create sequence seq_job_test1_no ;

Sequence created.

SCOTT>create or replace procedure insert_job_test
  2  is
  3  begin
  4  insert into scott.job_test1 (no, name)
  5  values(seq_job_test1_no.nextval, dbms_random.string('a',2)) ;
  6  commit ;
  7  end ;
  8  /

Procedure created.

SCOTT>begin
  2  dbms_scheduler.create_job (
  3  job_name => 'insert_job_test1',
  4  job_type => 'PLSQL_BLOCK',
  5  job_action => 'BEGIN insert_job_test; END;',
  6  start_date => systimestamp,
  7  repeat_interval => 'freq=secondly; interval=3') ;
  8  end ;
  9  /

PL/SQL procedure successfully completed.


SCOTT>exec dbms_scheduler.enable('insert_job_test1') ;

PL/SQL procedure successfully completed.

SCOTT>exec dbms_scheduler.run_job('insert_job_test1') ;

PL/SQL procedure successfully completed.

SCOTT>alter session set nls_date_format = 'YYYY-MM-DD:HH24:MI:SS' ;

Session altered.

SCOTT>select * from job_test1 order by 3 ;


3초마다 한번씩 insert 되는 것이 확인된다.



2) 현재 작동 중인 job 확인하기


SYS>  select p.job_name, p.job_type, o.object_id, p.enabled, o.last_ddl_time, o.created, cast(p.next_run_date as date) next_run_date, p.state, p.job_class, o.owner, schedule_type
  2  from dba_objects o, dba_scheduler_jobs p
  3  where o.owner = p.owner
  4  and o.object_name = p.job_name
  5  and o.object_type = 'JOB'
  6* and o.owner = 'SCOTT'



3) 특정 job 을 일시 중지 또는 재시작 하기

SCOTT>exec dbms_scheduler.disable ('insert_job_test1') ;

PL/SQL procedure successfully completed.

SCOTT>exec dbms_scheduler.enable ('insert_job_test1') ;

PL/SQL procedure successfully completed.




4) 특정 job 을 삭제하기

SCOTT>begin
  2  dbms_scheduler.drop_job('insert_job_test1') ;
  3  end ;
  4  /

PL/SQL procedure successfully completed.





5) DBMS_SCHEDULER.CREATE_JOB 자세히 살펴보기

SCOTT>begin
  2  dbms_scheduler.create_job (
  3  job_name => 'insert_job_test1',
  4  job_type => 'PLSQL_BLOCK',
  5  job_action => 'BEGIN insert_job_test; END;',
  6  start_date => systimestamp,
  7  repeat_interval => 'freq=secondly; interval=3') ;
  8  end ;
  9  /

2번 줄은 신규 job 생성
3번 dbms_scheduler 내에서 사용될 job 의 이름 지정
4번 5번 줄에 적히는 항목에 따라 값이 달라짐
5번 실제 실행될 프로그램을 적는 부분
실제 pl/sql 블록을 적을 수 있고
프로시저 이름을 적을 수 있고
os 에 있는 실행파일 이름을 지정할 수 있고
program_name 으로 미리 생성해둔 프로그램 이름을 지정할 수 있고
chained 값으로 생성된 체인을 활용할 수도 있다
4번 만약 5번 줄에 프로시저 이름을 적었다면 4번줄에는
'EXECUTABLE' 로 적어야 한다.
6번 해당 job 이 처음 시작될 시간을 지정하는 곳
systimestamp 는 지금 즉시 시작하라는 뜻이며 만약 지금 시간이 아닌 특정 시간에 시작하도록 지정하고 싶으면
start_date => to_timestamp_tz('2013-04-01 02:00:00 ROK', 'YYYY-MM-DD HH24:MI:SS TZR') 
2013 년 4월 1일 새벽 2시에 특정 job 을 시작하라는 의미
종료하는 시간을 지정하고 싶다면
end_date => systimestamp + interval '30' day
end_date => to_timestamp_tz ('2013-04-31 24:00:00 ROK', 'YYYY-MM-DD HH24:MI:SS TZR')
7번 반복할 주기 지정
1) 얼마마다 한번씩 수행
repeat_interval => 'FREQ=HOURLY; INTERVAL=1'        1시간 간격
repeat_interval => 'FREQ=MINUTELY; INTERVAL=30'    30분 간격
repeat_interval => 'FREQ=SECONDLY; INTERVAL=5'    5초 간격
repeat_interval => 'FREQ=WEEKLY; INTERVAL=2'        2주 간격
repeat_interval => 'FREQ=MONTHLY ;                        매달
repeat_interval => 'FREQ=YEARLY ;                            매년 수행

by 절을 사용하면 보다 구체적으로 시간 지정
repeat_interval => 'FREQ=YEARLY; BYWEEKNO=8,16,24,32,40,48; BYDAY=FRI;'

보다 구체적으로 매주 금요일 밤 23:50분
repeat_interval => 'FREQ=WEEKLY; BYDAY=FRI; BYHOUR=23; BYMINUTE=50;'

BY 절에 사용할 수 있는 세부사항
BYMONTH           JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC
BYWEEKNO         1 - 53
BYYEARDAY        1 - 366
BYMONTHDAY     1 - 31
BYDATE              MMDD 형태로 월일을 직접 지정가능
BYDAY                MON, TUE, WED, THU, FRI, SAT, SUN
BYHOUR              0 - 23
BYMINUTE           0 - 59
BYSECOND          0 - 59

INCLUDE 옵션 (다른 일정을 현재 일정에 포함할 수 있도록) 사용법

BEGIN
dbms_scheduler.create_schedule(
schedule_name => 'sub_sched_1',
repeat_interval => 'FREQ=YEARLY;BYDATE=0101, 0201, 0301') ;

dbms_scheduler.create_schedule(
schedule_name => 'main_sched',
repeat_interval =>
'FREQ=MONTHLY;INTERVAL=2;BYMONTHDAY=15;BYHOUR=9,17;INCLUDE=sub_sched_1') ;
END ;
/

2) 다음 직접 작업 시간까지의 간격 지정하기

repeat_interval => 'SYSDATE + 1'            하루 뒤에 수행
repeat_interval => 'SYSDATE + 30/1440'    1440은 하루를 분으로 환산한 것이니 30분 마다 수행하라는 뜻


6) 외부 스크립트를 생성해서 실행하기
먼저 해당 스크립트를 실행할 권한과 그룹이 지정되어 있는 externaljob.ora 라는 파일을 수정해야 한다.
유저명을 oracle 로 바꾸고, 사용 그룹명을 oracle 계정의 소속 그룹으로 변경한 후 SetUID 를 지정하면 된다.

step1 externaljob.ora 파일의 내용을 수정한다.

$ vi /app/oracle/product/11g/rdbms/admin/externaljob.ora



만약 oracle 계정의 소속 그룹을 모를 경우 아래와 같이 조회하세요
$ id oracle

step2 수정 완료 후 위 파일의 권한을 640 상태로 설정한다. 이 값이 기본값으로 설정되어 있다.

$ ls -l $ORACLE_HOME/rdbms/admin/externaljob.ora



step3 외부 스크립트를 실제로 수행하는 명령인 extjob 파일의 소유자를 변경한다.
SetUID 를 설정하는 방법은 chmod 4750 extjob 인데 기본적으로 설정되어 있다.
파일의 소유자 root 를 oracle 로 변경해주세요.

$ ls -l $ORACLE_HOME/bin/extjob
$ su -
암호:
# cd /app/oracle/product/11g/bin/
# chown oracle extjob
# ls -l extjob



step4 sys 계정으로 오라클에 접속해서 external job 을 수행할 계정에게 적절한 권한을 부여한다.

SYS>grant execute on sys.dbms_scheduler to scott ;

Grant succeeded.

SYS>grant create job to scott ;

Grant succeeded.

SYS>grant create external job to scott ;





step5 수행할 외부 스크립트 생성


[oracle@server108 ~]$ vi mkdir.sh

#!/bin/bash

date=`date +%Y-%m-%d-%H-%M-%S`

mkdir /app/oracle/$date




[oracle@server108 ~]$ chmod 755 mkdir.sh

[oracle@server108 ~]$ sh mkdir.sh

[oracle@server108 ~]$ sh mkdir.sh

[oracle@server108 ~]$

[oracle@server108 ~]$ ls /app/oracle/2013*



스크립트가 정상 작동하는 것을 확인

step6 위 스크립트를 수행하는 schedule 을 생성

SCOTT>begin
  2  dbms_scheduler.create_schedule (
  3  schedule_name => 'test_dir',
  4  start_date => systimestamp,
  5  end_date => null,
  6  repeat_interval => 'freq=secondly;interval=10');
  7  end ;
  8  /



step7 위 스크립트를 실행하는 job 생성

SCOTT>begin
  2  dbms_scheduler.create_job (
  3  job_name => 'test_dir_1',
  4  job_type => 'EXECUTABLE',
  5  job_action => '/home/oracle/mkdir.sh',
  6  schedule_name => 'test_dir' ) ;
  7  end ;
  8  /





step8 해당 job 을 enable

SCOTT>begin
  2  dbms_scheduler.enable('test_dir_1') ;
  3  end ;
  4  /




step9 해당 job을 실행

SCOTT>exec dbms_scheduler.run_job('test_dir_1') ;




step10 10초 간격으로 생성되는지 확인

[oracle@server108 ~]$ ls /app/oracle/2013*




오라클에서 아래와 같이 조회해도 된다.

SCOTT> select log_date, owner, job_name, status from user_scheduler_job_run_details where owner = 'SCOTT' order by log_date desc ;

위 job 은 테스트 용이므로 확인 후 삭제하여야 한다.

SCOTT>begin
  2  dbms_scheduler.drop_job('TEST_DIR_1') ;
  3  end ;
  4  /




(4) job 속성 변경하기
실습을 위해 새로운 job 생성
SCOTT>begin
  2  dbms_scheduler.create_job (
  3  job_name => 'insert_job_test2',
  4  job_type => 'PLSQL_BLOCK',
  5  job_action => 'BEGIN insert_job_test; END;',
  6  start_date => systimestamp,
  7  repeat_interval => 'freq=secondly; interval=5') ;
  8  end ;
  9  /


5초에 1번을 10초에 1번으로 변경

SCOTT>exec dbms_scheduler.set_attribute(name => 'insert_job_test2', attribute => 'repeat_interval', value => 'freq=secondly; interval=10') ;

PL/SQL procedure successfully completed.

확인은 SYS 계정으로

SYS>select owner, job_name, start_date, repeat_interval, end_date
  2  from dba_scheduler_jobs
  3  where owner = 'SCOTT' ;



(5) DBMS_SCHEDULER 관리하기

1) 생성된 job을 즉시 실행하기

exec dbms_scheduler.run_job('insert_job_test1') ;


2) job 을 중단하기

exec dbms_scheduler.stop_job(job_name => 'insert_job_test1', force => true) ;


3) job 삭제하기

exec dbms_scheduler.drop_job(job_name => 'insert_job_test1', force => true) ;


해당 job이 실행 중이라도 force 옵션이 true 이기 때문에 강제로 취소시키고 삭제한다.



반응형