ORACLE JOB은 PLSQL_BLOCK, STORED_PROCEDURE만 구동된다고 한다.
오라클 10g에서부터 ORACLE SCHEDULER 를 지원한다.
ORACLE JOB과 ORACLE SCHEDULER 가장 큰 차이점이라면
OS상의 crontab에 등재되는 shell프로그램도 ORACLE SCHEDULER 에서 돌릴 수 있다는 점.
오라클스케쥴러 등록을 위한 권한은 다음과 같다.
- GRANT CREATE ANY JOB TO 계정명;
오라클 스케쥴러에는 다음과 같은 명령어가 있다.
1. DBMS_SCHEDULER.CREATE_PROGRAM
- 잡이 스케쥴러에 맞게 돌면서 실제로 동작하는 프로그램(외부의 shell이나 SP, PLSQL_BLOCK 등) 을 등록한다.
2. DBMS_SCHEDULER.CREATE_SCHEDULER
- 주기적으로 돌아갈 스케쥴을 등록 한다
3. DBMS_SCHEDULER.CREATE_JOB
- 수행할 작업을 등록한다.
사용 절차
1. 동작할 프로그램 등록
BEGIN
DBMS_SCHEDULER.CREATE_PROGRAM(
program_name => 'STATS_MAIN_BATCH_PROGRAM',
program_action => 'STATS_MAIN_BATCH',
program_type => 'STORED_PROCEDURE',
comments => 'Service desk stats main batch program',
enabled => TRUE);
END;
1-1. 매개변수가 있는 경우
BEGIN
DBMS_SCHEDULER.CREATE_PROGRAM (
PROGRAM_NAME => 'STATS_MAIN_BATCH_PROGRAM'
,PROGRAM_TYPE => 'STORED_PROCEDURE'
,PROGRAM_ACTION => 'STATS_MAIN_BATCH'
,NUMBER_OF_ARGUMENTS => 1
,ENABLED => FALSE
,COMMENTS => 'SERVICE DESK STATS MAIN BATCH PROGRAM');
DBMS_SCHEDULER.DEFINE_PROGRAM_ARGUMENT (
PROGRAM_NAME => 'STATS_MAIN_BATCH_PROGRAM'
,ARGUMENT_POSITION => 1
,ARGUMENT_NAME => 'I_DT'
,ARGUMENT_TYPE => 'VARCHAR2'
,DEFAULT_VALUE => 'TO_CHAR(SYSDATE-1, ''YYYYMMDD'')'
);
DBMS_SCHEDULER.ENABLE(NAME => 'STATS_MAIN_BATCH_PROGRAM');
END;
/*-------------------------------------------------------------------------------------------------------------------
program_name: 프로그램이름
program_action: 실제 액션이 일어나는 SP(미리 등록되어있어야 한다). 여기서 shell 프로그램등을 돌릴 수도 있다.
program_type: SP 라고 명시
number-of_arguments: 사용할 인수 개수
comments: 코멘트.부가설명
enabled: 사용가능 설정
argument_position: 몇번째 인수인지
argument_name: 인수이름
argument_type: 인수타입
argument_value: 인수값
--------------------------------------------------------------------------------------------------------------------*/
2. 스케쥴 등록
BEGIN
DBMS_SCHEDULER.CREATE_SCHEDULE(
schedule_name => 'SCHEDULE_DAILY_AM_3_HOUR',
start_date => TRUNC(SYSDATE)+1 +3/24,
end_date => null,
repeat_interval => 'FREQ=DAILY;INTERVAL=1',
comments => 'Every AM 03 HOUR');
END;
/*-------------------------------------------------------------------------------------------------------------------
schedule_name: 스케쥴 이름
start_date: 스케쥴이 작동을 시작 할 시각. 입력한 시점부터 스케쥴러가 시작된다. AM 03시로 설정함
end_date: 스케쥴이 작동을 멈출 시간.
repeat_interval: 스케쥴이 작동하는 주기. 하루 한번 돌게 설정 매일 AM 03시에 동작함.
comments: 부가설명
--------------------------------------------------------------------------------------------------------------------*/
3. JOB 등록, 실제 수행 될 작업으로 스케쥴러와 프로그램을 명시해준다.
BEGIN
DBMS_SCHEDULER.CREATE_JOB (
job_name =>'STATS_MAIN_BATCH_JOB',
program_name =>'STATS_MAIN_BATCH_PROGRAM',
schedule_name =>'SCHEDULE_DAILY_AM_3_HOUR',
comments => 'Service desk stats main batch program',
--job_class =>'SCHEDULER_JOB_CLASS',
enabled =>TRUE);
END;
/*-------------------------------------------------------------------------------------------------------------------
job_name: 작업이름
program_name: 구동 될 프로그램이름 명시. 위에서 등록한 프로그램이름을 적어준다.
schedule_name: 어떤 스케쥴러가 돌면서 이 작업을 수행 할 것인가. 위에 등록한 스케쥴러이름을 적어준다.
job_class: JOB을 Class 라는 단위로 그룹핑해서 관리한다. 많은 양의 스케쥴러 관리를 위해 추가 할 수 있다.
하지만 잘 모르니까 난 안쓴다.
enabled: 사용가능 설정
comments: 코멘트.부가설명
--------------------------------------------------------------------------------------------------------------------*/
4. 삭제
execute dbms_scheduler.drop_job('FRG_BALANCE_HIST_UPDATE_JOB',false);
execute dbms_scheduler.drop_program('FRG_BALANCE_HIST_UPDATE_PRG',false);
execute dbms_scheduler.drop_schedule('SCHEDULE_30_MIN',false);
job먼저 지우고 program 지운다. program 먼저 지우려고 하면 종속된 객체라면서 안지워짐.
BEGIN
DBMS_SCHEDULER.DROP_JOB(
JOB_NAME => 'STATS_MAIN_BATCH_JOB',
FORCE => FALSE);
END;
BEGIN
DBMS_SCHEDULER.DROP_PROGRAM(
PROGRAM_NAME => 'STATS_MAIN_BATCH_PROGRAM',
FORCE => FALSE);
END;
5. 등록 정보 확인
SELECT * FROM USER_SCHEDULER_JOBS; --등록된 job
SELECT * FROM USER_SCHEDULER_JOB_ARGS; --job의 arguments
SELECT * FROM USER_SCHEDULER_RUNNING_JOBS; --현재 running중인 job들의정보
SELECT * FROM USER_SCHEDULER_JOB_LOG; --job의 log
SELECT * FROM USER_SCHEDULER_JOB_RUN_DETAILS; --job의수행된정보및Error 정보
SELECT * FROM USER_SCHEDULER_PROGRAMS; -- 등록된 Program
SELECT * FROM USER_SCHEDULER_PROGRAM_ARGS; -- 프로그램의 매게변수
SELECT * FROM USER_SCHEDULER_SCHEDULES; --등록된 스케쥴러
참고사항
1. JOB_CLASS 설정
BEGIN
DBMS_SCHEDULER.CREATE_JOB_CLASS (
job_class_name =>'SCHEDULER_JOB_CLASS',
logging_level =>DBMS_SCHEDULER.LOGGING_FULL,
log_history =>1,
comments =>'SCHEDULER_JOB_CLASS');
END;
2. 위의 내용은 PROGRAM, SCHEDULE, JOB 세 개로 세분화하여 등록하는 형태이다.
하지만 세개 모두 등록하지 않고 CREATE_JOB 한 개만 등록하여 사용하는 방법도 있다.
실제로 select * from user_scheduler_jobs; 으로 테이블을 살펴보면
CREATE_PROGRM에서 사용했던 program_type, program_action과 같이
job_type, job_action 컬럼이 존재하고
CREATE_SCHEDULE에서 사용했던 start_date, end_date, repeat_interval이 존재한다.
아마도 JOB 생성시 다 같이 작성하여 등록하고 사용하는것으로 보인다.
DBMS_SCHEDULER 패키지
- 개선판이라기보다는 완전히 새로 추가된 패키지
- DBMS_JOB - 특정 시간 및 간격으로 특정 작업을 수행
- DBMS_SCHEDULER - 매우 복잡하고 정교한 수준의 스케줄 작업 가능
DBMS_SCHEDULER 의 장점
- GUI(EM)을 통해서 손쉬운 관리
- 모듈화된 스케줄 오보젝트를 통해서 쉽게 공유할수 있다. ( 프로그램, 스케줄, 잡 )
- 모든 스케줄 활동이 기록된다.
- TimeZone 이 지원된다.
- 디비간 이동시 손쉽다(By DataPump)
● 프로그램(Program)
- 실행 가능한 프로그램(Program)을 말함
- DBMS_JOB 은 PL/SQL 블록, 저장 프로시저(Stored Procedure)만 가능
- DBMS_SCHEDULER는 외부 프로그램까지 사용 가능
( PL/SQL 블록, 저장 프로시저(Stored Procedure), 실행 파일(Executable, Unix Shell, Windows 실행 파일) ) - DBMS_SCHEDULER.CREATE_PROGRAM 프로시져를 통해 등록 가능하며
- [ALL/DBA/USER]_SCHEDULER_PROGRAMS 뷰를 통해서 확인 가능
- 스케줄렁에 의해서 실행 되는 무엇( 프로그램 이름, 타입, Argument 갯수 등 )
● 스케줄(Schedule)
- 작업을 수행할 스케줄을 말함.
- 작업 시작 시간, 종료 시간, 간격 등을 지정할 수 있다.
- DBMS_JOB에 비해 유연함
EX ) "FREQ=YEARLY; BYMONTH=4; BYMONTHDAY=15; BYHOUR=9; BYMINUTE=0; BYSECOND=0"
매년 4월 15일 9시에 작업 수행 - DBMS_SCHEDULER.CREATE_SCHEDULE 프로시져를 통해 등록 가능하며
- [ALL/DBA/USER]_SCHEDULER_SCHEDULES 뷰를 통해서 확인 가능
★WHEN / HOW MANY 에 대한 정의
#. USING PL/SQL Expression
: repeat_interval =>'sysdate+36/24'
#. Using Calendar Expression
: i) repeat_interval => 'FREQ=HOURLY;INTERVAL=4' ( Indiates a repeat interval of every four hours )
ii) repeat_interval => 'FREQ=YEARLY;BYMONTH=MAR,JUN,SEP,DEC;BYMONTH=15'
( indicate as repeat interval of every year on Mar 15th, Jun 15th, Sep 15th and Dec 15th )
● 작업(Job)
- 주어진 프로그램과 스케줄에 따라 수행할 작업을 말함 ( 언제 무엇을 )
- 명시적으로 생성된 프로그램과 스케줄을 이용할 수도 있고,
- 작업을 생성하면 암묵적인 프로그램과 스케줄을 생성할 수도 있다.
- DBMS_SCHEDULER.CREATE_JOB 프로시져를 통해 등록 가능하며
- [ALL/DBA/USER]_SCHEDULER_JOBS 뷰를 통해 확인 가능
- 작업이 수행되면서 남는 로그 데이터는 [ALL/DBA/USER]_SCHEDULER_JOB_LOG 뷰나
- [ALL/DBA/USER]_SCHEDULER_JOB_RUN_DETAILS 뷰를 통해 확인 가능
● 작업 클래스(Job Class)
- 작업의 공통 속성을 묶어서 만든 분류를 말한다.
- Resouce Consumer Group, Service, Logging Level, Log History 의 속성을 조합해서 하나의 클래스 생성 한다.
- Resource Consumer Group 은 DBMS_RESOURCE_MANGER 패키지를 통해서 생성,
- 말 그대로 자원을 얼마나 사용 가능하게 할지를 지정
- Service는 작업이 특정 서비스에 대한 리소스 친화도(Resource Affinity)를 가지도록 지정
[ Service는 RAC 에서 클러스터 내의 여러 노드를 묶은 논리적인 그룹 ] - Logging Level 은 작업 실행에 대한 로그 데이터의 레벨을 지정
- Log History 는 로그 데이터를 얼마나 저장할 지를 지정한다
- 같은 작업 클래스에 속하는 작업은 같은 속성을 공유하기 때문에 관리상의 편의점을 제공
- 하나의 JOB 은 하나의 JOB CLASS 에만 속함
● 윈도우(Window)
- 특정 리소스 플랜(Resoure Plan)을 적용하는 시간 단위를 의미
- 리소스 플랜은 오라클이 자원을 관리하는 단위로, 작업의 종류에 따라 CPU 등의 자원을 얼마나 부여할 지를 지정하는 역할
( 윈도우를 지정하면 해당 윈도우 안에서 실행되는 작업은 윈도우 생성시 지정한 리소스 플랜을 사용하게 된다
● 체인(Chain )
- 프로그램의 집합을 의미 한다. 일련의 프로그램들을 순서대로 수행하고자 할 경우에 사용한다.
- 체인은 오라클 10g R2 에서 추가된 기능
스케줄작업과 RAC Instance
- DBMS_JOB ==> 작업을 실행할 인스턴스 번호를 지정 // 한노드로 지정 시에 좀 더 편리
- DBMS_SCHEDULER => Instance_Stickness 라는 개념을 통해 좀 더 지능적으로 인스턴스를 할당
INSTANCE_STICKSNESS = TRUE ( DBMS_SCHEDULER.SET_ATTRIBUTE ) 의미
- 작업 수행 시 현재 가장 부하가 적은 인스턴스에 작업을 분배 한다.
- 이후 작업 수행 시에는 가능한 최초에 지정된 인스턴스에서 작업을 수행하도록 한다.
이 매커니즘을 일컬어 인스턴스 접착도라고 하며 리소스 친화도를 구현하는 방법 - 최초에 지정된 인스턴스가 다운되거나, 부하가 심해서 작업을 수행할 수 없을 경우 다른 인스턴스에서 작업을 수행
- 만일 INSTANCE_STICKNESS 속성 값이 FALSE 이면 오라클은 인스턴스 순서대로 작업을 수행한다.
즉, DBMS_JOB 패키지를 이용해 작업을 수행하되 인스턴스 번호를 지정하지 않은 경우와 거의 같은 방식으로 작동한다.
-----------------------------------------------------------------------------------------------------------------------------------------------------------------
CREATE TABLE TBL_TEST(
NOW_COL VARCHAR2(14)
);
CREATE OR REPLACE PROCEDURE PR_TEST(P_NOW_COL IN VARCHAR2)
AS
BEGIN
INSERT INTO TBL_TEST(NOW_COL) VALUES (P_NOW_COL);
COMMIT;
BEGIN
DBMS_SCHEDULER.CREATE_JOB (
JOB_NAME => 'PR_TEST_JOB'
, START_DATE => TRUNC(SYSDATE+1)+6/24
, REPEAT_INTERVAL => 'FREQ=DAILY;INTERVAL=1'
, END_DATE => NULL
, JOB_CLASS => 'DEFAULT_JOB_CLASS'
, JOB_TYPE => 'PLSQL_BLOCK'
, JOB_ACTION => 'BEGIN PR_TEST(TO_CHAR(SYSDATE,''YYYYMMDDHH24MISS'')); END;'
, COMMENTS => 'JOB 등록 예제'
);
DBMS_SCHEDULER.ENABLE('PR_TEST_JOB');
END;
SELECT * FROM ALL_SCHEDULER_JOBS WHERE JOB_NAME = 'PR_TEST_JOB';
SELECT * FROM ALL_SCHEDULER_JOB_LOG;
SELECT * FROM ALL_SCHEDULER_JOB_RUN_DETAILS;
-- 또는
SELECT * FROM USER_SCHEDULER_JOB_LOG;
SELECT * FROM USER_SCHEDULER_JOB_RUN_DETAILS;
-- DETAILS이 붙은 스케줄러 잡 로그 VIEW 테이블은 실행 실패 에러 내용을 조회 할 수 있음
1) JOB_NAME
샘플에서는 "PR_TEST_JOB" 등록했습니다.
잡 이름은 등록된 잡 이름 중에서 유니크하기만 하면 되고 스케줄러에서 잡을 삭제 할 때 잡 이름을 파라미터러 입력하여 삭제 합니다.
2) START_DATE 와 REPEAT_INTERVAL
START_DATE와 REPEAT_INTERVAL은 스케줄러에 등록한 잡이 일정 시간마다 반복되도록 하는 옵션으로 서로 연관 관계가 있습니다.
START_DATE는 잡이 최초로 실행되는 시간을 지정하며 REPEAT_INTERVAL은 반복되는 형식을 지정합니다.
샘플의 "TRUNC(SYSDATE+1)"은 내일을 의미합니다.
SELECT TRUNC(SYSDATE+1) FROM DUAL;
이렇게 쿼리를 실행하면 내일 일자가 나올겁니다.
그럼 오늘은?
"TRUNC(SYSDATE)"로 입력하면 되겠죠?
잡 등록 샘플의 6/24는 오전 6시를 의미하는 값입니다.
3) END_DATE
잡의 만료 시간입니다.
영구적으로 반복적으로 실행 되기를 바라면 NULL을 입력합니다.
일주일만 실행되기를 바라면 "TRUNC(SYSDATE+7)" 등으로 등록하면 됩니다.
4) COMMENTS
comments는 스케줄러 잡의 설명문이며 ALL_SCHEDULER_JOBS VIEW를 조회하면 확인 할 수 있습니다.
-- 잡(job) 삭제
EXEC DBMS_SCHEDULER.DROP_JOB('PR_TEST_JOB');
-- 프로시저 삭제
DROP PROCEDURE TEST01.PR_TEST;
-- 테이블 삭제
DROP TABLE TEST01.TBL_TEST;
-----------------------------------------------------------------------------------------------------------------------------------------------------------------
DBMS_JOB : 특정 시간 및 간격으로 작업을 수행
DBMS_SCHEDULER : DBMS_JOB을 업그레이드한 버전으로 매우 복잡하고 정교한 수준의 스케줄 작업 가능
01. DBMS_JOB
PL/SQL블록, Stored Procedure만 사용 가능하고 아래와 같은 권한이 필요하다.
GRANT CREATE ANY JOB TO 계정명;
<예시> 현재 시간을 저장하는 프로시저를 주기적으로 호출하는 JOB
1) 테이블 생성
CREATE TABLE JOB_TEST (reg_date date);
2) 프로시저 생성
CREATE OR REPLACE PROCEDURE PR_JOB_TEST2
IS
BEGIN
INSERT INTO JOB_TEST VALUES (sysdate);
COMMIT;
END;
3) JOB 등록
DECLARE
V_JOB BINARY_INTEGER := 100;
BEGIN
DBMS_JOB.SUBMIT(V_JOB,
'PR_JOB_TEST2;'
,SYSDATE
,'SYSDATE+1/24/60' -- 1분마다 실행
,FALSE);
COMMIT;
END;
-- 'sysdate+1/24/60' : 1분에 1회 실행
-- 'sysdate+1/24' : 1시간에 1회 실행
-- 'sysdate+1' : 하루에 1회 실행
-- 'sysdate+7': 일주일에 1회 실행
-- 'trunc(sysdate+1)+2/24' : 다음날 2시에 1회 실행
-- 'next_day(sysdate, "TUESDAY")' : 매주 화요일에 실행
-- 'null' : 처음 1회 실행 후 없음
4) JOB 조회
SELECT JOB, LOG_USER, LAST_DATE, LAST_SEC, INTERVAL FROM DBA_JOBS;
5) JOB 삭제
EXEC DBMS_JOB.REMOVE(job_number);
02 DBMS_SCHEDULE
Scheduler는 DBMS_JOB보다 확장된 기능을 제공한다.(오라클 10g부터 사용 가능)
Job과 가장 큰 차이점은 Job에서 불가능하던 외부 스크립트를 실행할 수 있다.
주요특징
① GUI(EM)을 통해서 손쉬운 관리 가능
② 오라클에서 생성된 프로시저나 함수 외에도 OS에서 생성된 각종 유틸, 프로그램까지도 사용 가능
③ DB 내부 이벤트까지 추적 가능하기 떄문에 OS나 JOB 보다 다양하게 작업을 수행할 수 있음
④ DB간 이동이 쉬움 (DataPump 이용)
구성
① Program
- 실행 가능한 프로그램(Program)을 지칭
- Job은 PL/SQL 블록, 프로시저만 가능하나 Scgeduler는 외부 프로그램까지 사용 가능
- DBMS_SCHEDULER.CREATE_PROGRAM 프로시져로 등록
- [ALL/DBA/USER]_SCHEDULER_PROGRAMS를 이용하여 조회
② Schedule
- dbms_scheduler가 실제 수행할 시간이나 실행 주기 등을 생성
- dbms_job 에 비해 유연함 (ex) "FREQ=YEARLY; BYMONTH=4; BYMONTHDAT=15; BYHOUR=9; BYMINUTE=0; BYSECOND=0" : 매년 4월 15일 9시에 작업 수행
- DBMS_SCHEDULER.CREATE_SCHEDULE 프로시져로 등록
- [ALL/DBA/USER]_SCHEDULER_PROGRAMS 를 이용하여 조회
③ Job
- 수행할 작업(Job)을 말함 (언제, 무엇을)
- DBMS_SCHEDULER.CREATE_JOB 프로시져로 등록
- [ALL/DBA/USER]_SCHEDULER_JOBS 를 이용하여 조회
④ Job Class
- 작업(Job)의 공통 속성을 묶어서 만든 분류
⑤ Window
- 특정 Resource Plan을 적용하는 시간 단위를 의미
<예시> 현재시간을 저장하는 프로시저를 주기적으로 호출하는 JOB
1) 테이블 생성
CREATE TABLE JOB_TEST (reg_date date);
2) 프로시저 생성
CREATE OR REPLACE PROCEDURE PR_JOB_TEST2
IS
BEGIN
INSERT INTO JOB_TEST VALUES (sysdate);
COMMIT;
END;
3) Program 생성
BEGIN
DBMS_SCHEDULER.CREATE_PROGRAM(
PROGRAM_NAME=>'PRM_JOB_TEXT',
PROGRAM_ACTION=>'PR_JOB_TEST',
PROGRAM_TYPE=>'STORED_PROCEDURE',
ENABLED=>TRUE
);
END;
4) Scheduler 생성
BEGIN
DBMS_SCHEDULER.CREATE_SCHEDULE(
SCHEDULE_NAME=>'SC_JOB_TEST',
START_DATE=>TRUNC(SYSDATE)+1+9/24,
END_DATE=>NULL,
REPEAT_INTERVAL=>'FREQ=DAILY;INTERVAL=1',
COMMENTS=>'매일 아침9시에 수행하는 스케줄러 수행'
);
END;
5) JOB 생성
BEGIN
DBMS_SCHEDULER.CREATE_JOB(
JOB_NAME=>'NPR_JOB_TEST',
PROGRAM_NAME=>'PRM_JOB_TEXT',
SCHEDULE_NAME=>'SC_JOB_TEST',
ENABLED=>TRUE,
COMMENTS=>'매일 09시에 스케줄러 동작'
);
END;
6) 조회
SELECT * FROM DBA_JOBS; -- JOB 확인
SELECT * FROM DBA_SCHEDULER_JOBS WHERE OWNER = 'TEST01'; -- 스케줄러 확인
SELECT * FROM DBA_SCHEDULER_PROGRAMS WHERE OWNER = 'TEST01'; -- 프로그램 확인
JOBS = WHAT 과 INTERVAL이 존재한다. 프로그램 = WHAT, 스케줄러 = INTERVAL, 프로그램 + 스케줄러 = 잡 개념으로 생각하면 이해하기 좋다.
'DB > Oracle' 카테고리의 다른 글
[Oracle] Chapter 12. 오라클 아키텍처와 동작에 관한 Q&A (0) | 2023.04.18 |
---|---|
[Oracle] ORA-01034: ORACLE not available 오류 해결법 (0) | 2023.03.30 |
[Oracle] 바인드 변수의 부작용과 해법 (0) | 2023.01.31 |
[Oracle] ORA-65096: 공통 사용자 또는 롤 이름이 부적합합니다. 에러 해결 (0) | 2023.01.25 |
[Oracle] Chapter 11. 백그라운드 프로세스의 동작과 역활 (0) | 2023.01.17 |