오라클 JOB을 스케줄링
2017. 2. 5. 22:34ㆍMeteor
오라클 JOB을 스케줄링
주기적으로 수행되어지는 JOB을 JOB QUEUE를 사용하여 스케줄링 할 수 있습니다.. JOB을 스케줄링 하기 위해.주기적으로 수행되어지는 JOB을 JOB QUEUE를 사용하여 스케줄링 할 수 있습니다..
잡의 변경
JOB을 스케줄링 하기 위해서 ORACLE의 DBMS_JOB 패키지를 이용합니다..
JOB QUEUE PROCESS가 JOB QUEUE 안의 잡을 수행합니다..
JOB으로 등록될 수 있는 것은 PL/SQL 프로시저 또는 패키지가 되며
예를 들어소스 디비의 테이블들에서 타겟 테이블로 데이터를 적재하는 프로시저를 생성했는데
1분단위로 데이터를 타겟 테이블로 적재를 해야 할 때 DBMS_JOBS에 등록하여
스케줄링 할 수 있습니다.
.JOB_QUEUE_PROCESSES 파라미터가 이와 관련된 초기화 파라미터로 0으로 설정되면
JOB QUEUE PROCESS는 시작되지 않으며 JOB QUEUE의 어느 잡도 수행되지 않습니다..
JOB_QUEUE_PROCESSES 파라미터의 MAX값이 설정되어야 오라클 인스턴스 위에서
동시에 잡을 수행할 수 있다. 설정할 수 있는 최고 값은 1000입니다..
JOB_QUEUE_PROCESSES=60 과 같이 설정할 수 있습니다..
.등록되거나 수행되는 잡에 대해서는 DBA_JOBS 또는 USER_JOBS 딕셔너리 뷰를 통해
확인 할 수 있다.
.JOB_QUEUE_PROCESSES 는 다이나믹 하게 DB를 SHUTDOWN하지 않고 ALTER SYSTEM
명령을 이용해서 설정할 수 있습니다.
ALTER SYSTEM SET JOB_QUEUE_PROCESSES = 20;
.JOB QUEUE안의 JOB을 스케줄링 하기 위해서는 DBMS_JOBS패키지를 사용할 수 있으며
JOB_QUEUE를 사용하기 위해 관련된 DB 권한은 없다.
.다음은 DBMS_JOBS의 패키지를 사용하기 위한 패키지의 프로시져들입니다.
SUBMIT - 잡큐의 잡을 등록합니다.
REMOVE - 잡큐의 잡을 제거합니다.
CHANGE - 잡큐의 잡을 변경합니다.
NEXT_DATE - 잡의 다음 수행시간을 변경합니다.
INTERVAL - 잡 수행 주기를 변경합니다.
WHAT - 잡으로 등록된 프로시저 또는 패키지를 변경합니다.
RUN - 잡을 수동으로 강제로 수행합니다.
.새 JOB을 JOB QUEUE에 등록하기 위해 사용되는 파라미터로 DBMS_JOB.SUBMIT()에 들어가느
파라미터 입니다.
JOB - OUTPUT 파라미터로 생성한 잡에 의해 할당되는 식별자 입니다.
WHAT - JOB QUEUE에 등록되는 PL/SQL 프로시저 또는 패키지 입니다.
NEXT_DATE - 잡이 수행되는 다음 시간입니다.
INTERVAL - 잡이 수행되는 주기로 초 단위까지 지정 가능합니다.
JOB_QUEUE에 등록하는 예제입니다.
01.
VARIABLE jobno NUMBER
02.
BEGIN
03.
DBMS_JOB.SUBMIT
04.
(
05.
:jobno,
06.
'SP_IN_EMP_SAL;'
,
07.
SYSDATE,
08.
'SYSDATE + 1'
09.
);
10.
COMMIT
;
11.
END
;
12.
/ <span class=
"Apple-style-span"
style=
"font-family: 굴림; white-space: normal;"
>
13.
</span>
위의 PL/SQL문을 SQL PLUS에서 수행합니다.
첫번째 파라미터가 JOB NUMBER가 부여되는 부분이고
두번째 파라미터가 WHAT으로 SP_IN_EMP_SAL이라는 프로시저를 등록했습니다.
세번째 파라미터가 NEXT_DATE이며 4번째 파라미터가 잡 수행 주기로 하루에 한번씩
수행하라는 의미입니다.
DBMS_JOB을 이용하면 특정시간, 특정요일, 특정일, 30초단위, 매분 정각, 매시정각
등 다양하게 잡을 스케줄링 하는 것이 가능합니다.
ETL 수행 할 때도 유용하게 사용할 수 있습니다.
잡 수행 간격 조정의 예
.SYSDATE+ 7 : 7일에 한번씩 잡이 수행됩니다.
.SYSDATE+1/24 : 1시간에 한번씩 잡이 수행됩니다.
.SYSDATE+30/86400 : 30초에 한번씩 잡이 수행됩니다.
.최초 잡 수행시간이 14:02분일 경우 매시 14:02분에 잡을 수행해야 될 경우
=>trunc(SYSDATE,'MI')+1/24
.최조 잡 수행시간이 06시 이고 매 8시간마다 정각에 잡이 수행되어야 될 경우
=>trunc(SYSDATE,'MI')+8/24
.매주 월요일 정각 3시에 잡이 수행되어야 할 경우
=>NEXT_DAY(TRUNC(SYSDATE),'MONDAY')+15/25
.각 분기마다 첫번째 월요일에 잡이 수행되어야 될 경우
=>NEXT_DAY(ADD_MONTHS(TRUNC(SYSDATE,'Q'),3),'MONDAY')
주의> dbms_job으로 잡을 스케줄링하게 될 경우 예를 들어 잡 최초 수행시간이 22일 14:00시이고
매시 정각에 잡이 수행되어야 할 경우 SYSDATE+1/24로 간격을 주게 되면 매 정시에 도는 것이
아니라 잡 수행 시간에 따라 약간씩 늦어지게 되어 14:00:04 => 15:00:07 => 16:00:10 이런식으로
잡 수행시간이 잡히게 됩니다. 따라서 정각에 수행되게 하려면 trunc함수를 이용해서 무조건 분에서
잘라내여 00으로 만들어 준다. trunc(SYSDATE,'MI')
잡의 삭제
1.
BEGIN
2.
DBMS_JOB.REMOVE(14443);
3.
END
;
4.
/
14443은 잡 번호 이다. USER_JOBS 데이터 딕셔너리 뷰를 보면 잡 번호를 알 수 있습니다.
1.
BEGIN
2.
DBMS_JOB.CHANGE(14144,
NULL
,
NULL
,
'SYSDATE + 3'
);
3.
END
;
4.
/
잡으로 등록된 프로시저/패키지 변경잡 다음 수행시간 변경잡 수행 간격 변경잡 수행 정지 잡이 BROKEN되면 잡은 수행되지 않으며 강제로 수행 할 시에는 DBMS_JOB.RUN()을 통해 수행합니다..잡큐 정보 VIEWING DBA_JOBS, USER_JOBS, ALL_JOBS를 이용합니다.DBMS_JOB의 활용예제를 주기적으로 소스테이블에서 타켓 테이블로 적재할 시 어떻게 사용할 수 있는지 간단하게 예를 만들었습니다
1.
BEGIN
2.
DBMS_JOB.WHAT(14144,
3.
'SP_IN_EMP_SAL;'
);
4.
END
;
5.
/
1.
BEGIN
2.
DBMS_JOB.NEXT_DATE(14144, TRUNC(SYSDATE,
'MI'
) + 4);
3.
END
;
4.
/
1.
BEGIN
2.
DBMS_JOB.INTERVAL(14144, TRUNC(SYSDATE,
'MI'
)+30/1440);
3.
END
;
4.
/
1.
BEGIN
2.
DBMS_JOB.BROKEN(14144,
TRUE
);
3.
END
;
4.
/
01.
SELECT
JOB, NEXT_DATE, NEXT_SEC, FAILURES, BROKEN
02.
FROM
DBA_JOBS;
03.
04.
JOB NEXT_DATE NEXT_SEC FAILURES B
05.
------- --------- -------- -------- -
06.
9125 01-JUN-01 00:00:00 4 N
07.
14144 24-OCT-01 16:35:35 0 N
08.
9127 01-JUN-01 00:00:00 16 Y
09.
3
rows
selected.
001.
--수행될 잡의 목록이 들어갈 테이블
002.
CREATE
TABLE
JOB_LIST
003.
(
004.
JOB_ID VARCHAR2(2),
005.
JOB_TYPE VARCHAR2(1),
006.
JOB_NAME VARCHAR2(30),
007.
JOB_EXEC_HOUR
VARCHAR
(2),
008.
JOB_PARENTID VARCHAR2(2),
009.
CONSTRAINTS JOB_LIST_PK
PRIMARY
KEY
(JOB_ID)
010.
USING
INDEX
011.
TABLESPACE CYS_INDEX PCTFREE 0 STORAGE(INITIAL 32K
NEXT
32K PCTINCREASE 0) NOLOGGING)
012.
TABLESPACE CYS_DATA PCTFREE 0 STORAGE(INITIAL 128K
NEXT
128K PCTINCREASE 0
013.
);
014.
/
015.
016.
CREATE
UNIQUE
INDEX
JOB_LIST_IDX01
ON
JOB_LIST(JOB_NAME,JOB_EXEC_HOUR)
017.
TABLESPACE CYS_INDEX PCTFREE 0 STORAGE(INITIAL 64K
NEXT
64K PCTINCREASE 0);
018.
/
019.
020.
-잡 수행 히스토리 테이블로 하루에 한번씩 JOB_LIST 테이블에서 LOG테이블로 JOB_LIST가 복사된다.
021.
CREATE
TABLE
JOB_LOG
022.
(
023.
JOB_ID VARCHAR2(2),
024.
JOB_EXEC_DATE VARCHAR2(8),
025.
JOB_START_TIME
DATE
,
026.
JOB_END_TIME
DATE
,
027.
JOB_DATASTART_TIME
DATE
,
028.
JOB_DATAEND_TIME
DATE
,
029.
JOB_STATUS VARCHAR2(1),
030.
JOB_ERR_MSG VARCHAR2(100),
031.
CONSTRAINTS JOB_LOG_PK
PRIMARY
KEY
(JOB_ID,JOB_EXEC_DATE) USING
INDEX
032.
TABLESPACE CYS_INDEX PCTFREE 0 STORAGE(INITIAL 128K
NEXT
128K PCTINCREASE 0) NOLOGGING,
033.
CONSTRAINTS JOB_LIST_FK
FOREIGN
KEY
(JOB_ID)
REFERENCES
JOB_LIST(JOB_ID))
034.
TABLESPACE CYS_DATA STORAGE(INITIAL 1M
NEXT
1M PCTINCREASE 0)
035.
036.
--JOB_ID를 부여하기 위한 시퀀스
037.
CREATE
SEQUENCE
JOB_NUM START
WITH
1 INCREMENT
BY
1 ;
038.
039.
--하루에 한번 DBMS_JOB을 이용하여 JOB_LIST의 JOB들을 JOB_LOG에 INSERT하기 위한 프로시져
040.
--다음날 수행할 JOB을 LOG로 넣는다.
041.
CREATE
OR
REPLACE
PROCEDURE
SP_IN_JOB_LOG(V_INDATE
IN
VARCHAR2
DEFAULT
NULL
)
042.
AS
043.
BEGIN
044.
INSERT
INTO
JOB_LOG
SELECT
JOB_ID,
045.
NVL(V_INDATE,TO_CHAR(SYSDATE+1,
'YYYYMMDD'
)),
046.
NULL
,
047.
NULL
,
048.
NULL
,
049.
NULL
,
050.
'N'
,
051.
NULL
052.
FROM
JOB_LIST;
053.
054.
COMMIT
;
055.
END
SP_IN_JOB_LOG;
056.
057.
--SP_IN_JOB_LOG 프로시저를 DBMS_JOB에 등록한다.
058.
DECLARE
059.
JOB_NUMBER NUMBER;
060.
BEGIN
061.
DBMS_JOB.SUBMIT(JOB_NUMBER,
--JOB번호
062.
'SP_IN_JOB_LOG;'
,
--프로시저명
063.
TO_DATE(
'20050208180000'
,
'YYYYMMDDHH24MISS'
),
--NEXT_DATE
064.
'TRUNC(SYSDATE,'
'MI'
')+1'
);
--잡 수행 간격(매일 정각 6시)
065.
END
;
066.
067.
--JOB_LIST에 수행할 프로시져(JOB)을 등록
068.
--DBA_USERS테이블을 이용해서 24개의 로우를 만들어 낸 후 카테시안 프러덕을 이용
069.
INSERT
INTO
JOB_LIST
070.
SELECT
JOB_NUM.NEXTVAL JOB_ID,
071.
JOB_TYPE,
072.
JOB_NAME,
073.
B.CNT JOB_EXEC_HOUR,
074.
NULL
075.
FROM
(
076.
SELECT
NULL
JOB_ID,
077.
'F'
JOB_TYPE,
078.
'SP_IN_F_SALE_SUM'
JOB_NAME,
079.
NULL
JOB_EXEC_HOUR,
080.
NULL
081.
FROM
DUAL) A,
082.
(
SELECT
LPAD(ROWNUM-1,2,
'0'
) CNT
FROM
DBA_TABLES
083.
WHERE
ROWNUM<25) B
084.
085.
COMMIT
;
086.
087.
--JOB_LIST를 JOB_LOG로 INSERT(현재 SP_IN_JOB_LOG 가 다음일을 INSERT하도록 되어 있으므로 해당일을 넣어줌)
088.
EXEC
SP_IN_JOB_LOG(
'20050208'
);
089.
090.
--제대로 들어갔는지 확인
091.
SELECT
*
FROM
JOB_LOG;
092.
093.
--SOURCE 테이블을 시간단위로 섬머리 해서 TARGET 테이블로 적재하기 위한 프로시져
094.
--ERROR없이 매 시간 돌 때는 파라미터 없이 SP_IN_F_SALE_SUM으로 수행 되고 수동으로 어떤 데이터의
095.
--범위를 적재해야 할 경우 시간의 범위를 파라미터로 넘겨줌
096.
CREATE
OR
REPLACE
PROCEDURE
SP_IN_F_SALE_SUM(V_STARTTIME
IN
VARCHAR2
DEFAULT
NULL
, V_ENDTIME
IN
VARCHAR2
DEFAULT
NULL
)
097.
AS
098.
D_STARTTIME
DATE
;
099.
D_ENDTIME
DATE
;
100.
V_ERR_MSG VARCHAR2(100);
101.
BEGIN
102.
103.
--프로시저가 파라미터 값이 없이 수행될 경우
104.
IF V_STARTTIME
IS
NULL
AND
V_ENDTIME
IS
NULL
THEN
105.
SELECT
NVL(JOB_DATAEND_TIME,TRUNC(SYSDATE-1/24,
'HH24'
))
106.
INTO
D_STARTTIME
107.
FROM
JOB_LOG
108.
WHERE
JOB_ID=(
SELECT
JOB_ID
FROM
JOB_LIST
109.
WHERE
JOB_NAME=
'SP_IN_F_SALE_SUM'
110.
AND
JOB_EXEC_HOUR=TO_CHAR(SYSDATE-1/24,
'HH24'
))
111.
AND
JOB_EXEC_DATE=TO_CHAR(SYSDATE,
'YYYYMMDD'
)
112.
AND
JOB_STATUS=
'Y'
;
113.
114.
D_ENDTIME:=TRUNC(SYSDATE,
'HH24'
);
115.
ELSE
116.
SELECT
NVL(JOB_DATAEND_TIME,TO_DATE(V_STARTTIME,
'YYYYMMDDHH24MISS'
))
117.
INTO
D_STARTTIME
118.
FROM
JOB_LOG
119.
WHERE
JOB_ID=(
SELECT
JOB_ID
FROM
JOB_LIST
120.
WHERE
JOB_NAME=
'SP_IN_F_SALE_SUM'
121.
AND
JOB_EXEC_HOUR=SUBSTR(V_STARTTIME,9,2))
122.
AND
JOB_EXEC_DATE=SUBSTR(V_ENDTIME,1,8)
123.
AND
JOB_STATUS=
'Y'
;
124.
125.
D_ENDTIME:=TO_DATE(V_ENDTIME,
'YYYYMMDDHH24MISS'
);
126.
END
IF;
127.
128.
--수행되는 프로시저의 START시간을 찍어주고 RUNNING으로 표시
129.
UPDATE
JOB_LOG
130.
SET
JOB_START_TIME=SYSDATE,
131.
JOB_STATUS=
'R'
132.
WHERE
JOB_ID=(
SELECT
JOB_ID
FROM
JOB_LIST
133.
WHERE
JOB_NAME=
'SP_IN_F_SALE_SUM'
134.
AND
JOB_EXEC_HOUR=SUBSTR(V_STARTTIME,9,2))
135.
AND
JOB_EXEC_DATE=SUBSTR(V_ENDTIME,1,8);
136.
137.
-- DML------
138.
139.
--수행되어질 INSERT문
140.
141.
-- DML-----
142.
143.
COMMIT
;
144.
145.
--프로시저가 ERROR없이 수행이 끝나면 END 시간과 가져온 데이터의 범위를 찍어줌
146.
UPDATE
JOB_LOG
147.
SET
JOB_END_TIME=SYSDATE,
148.
JOB_DATASTART_TIME=D_STARTTIME,
149.
JOB_DATAEND_TIME=D_ENDTIME,
150.
JOB_STATUS=
'Y'
151.
WHERE
JOB_ID=(
SELECT
JOB_ID
FROM
JOB_LIST
152.
WHERE
JOB_NAME=
'SP_IN_F_SALE_SUM'
153.
AND
JOB_EXEC_HOUR=TO_CHAR(D_ENDTIME,
'HH24'
))
154.
AND
JOB_EXEC_DATE=SUBSTR(V_ENDTIME,1,8);
155.
156.
COMMIT
;
157.
158.
EXCEPTION
159.
WHEN
OTHERS
THEN
160.
V_ERR_MSG:= SUBSTRB(SQLERRM, 1, 80);
161.
162.
UPDATE
JOB_LOG
163.
SET
JOB_END_TIME=SYSDATE,
164.
JOB_STATUS=
'E'
,
165.
JOB_ERR_MSG=V_ERR_MSG
166.
WHERE
JOB_ID=(
SELECT
JOB_ID
FROM
JOB_LIST
167.
WHERE
JOB_NAME=
'SP_IN_F_SALE_SUM'
168.
AND
JOB_EXEC_HOUR=TO_CHAR(D_ENDTIME,
'HH24'
))
169.
AND
JOB_EXEC_DATE=SUBSTR(V_ENDTIME,1,8);
170.
171.
COMMIT
;
172.
END
SP_IN_F_SALE_SUM;
173.
/
174.
175.
--SP_IN_F_SALE_SUM 프로시저를 DBMS_JOB에 등록합니다.
176.
DECLARE
177.
JOB_NUMBER NUMBER;
178.
BEGIN
179.
DBMS_JOB.SUBMIT(JOB_NUMBER,
--JOB번호
180.
'SP_IN_F_SALE_SUM;'
,
--프로시저명
181.
TO_DATE(
'20050209000000'
,
'YYYYMMDDHH24MISS'
),
--NEXT_DATE
182.
'TRUNC(SYSDATE,'
'MI'
')+1/24'
);
--잡 수행 간격(매시간 정각)
183.
END
;
JOB의 시간이나 간격 등록된 프로시저등을 변경하고자 할 때 DBMS_JOB의 다른 프로시져를 이용해서 변경합니다. 2번째 정리 부분에 설명되어 있습니다.
'Meteor' 카테고리의 다른 글
오라클 - DBMS_SCHEDULER (0) | 2017.02.05 |
---|---|
오라클 - 원하는 시간에만 DB 작업 실행하기 (0) | 2017.02.05 |
Oracle SQL performance with database links - db link (0) | 2017.01.29 |
오라클 DB Link 속도 저하 문제 (0) | 2017.01.29 |
Microservices with Meteor (0) | 2016.09.29 |