Search
Duplicate

스케줄러

스케줄러(DBMS_SCHEDULER)

정해진 시간 또는 주기에 따라 자동으로 작업(Job)을 실행하는 기능
오라클에서 시간 기반 자동 실행은 모두 스케줄러(Scheduler) 로 구현한다.
특정 시각 실행 (ex. 매일 3시)
반복 실행 (ex. 매 4초마다, 매 5분, 매 1시간)
복잡한 패턴 실행 (요일별, 월별, 특정 날짜 등)

스케줄러가 필요한 이유

트리거는 시간 기반 실행이 불가능하므로, 시간 기반 기능은 무조건 Scheduler 를 사용한다.
정기적인 데이터 처리 자동화
로그 정리 또는 백업 자동화
배치 프로그램 실행
반복적인 잡 처리
MySQL EVENT 와 동일한 역할 수행

스케줄러 주요 구성 요소

대부분의 경우 JOB 하나만 만들면 충분하다.
요소
설명
JOB
실행되는 실제 작업(가장 중요)
PROGRAM
실행 로직 정의(선택사항)
SCHEDULE
주기, 시간 패턴 정의(선택사항)
JOB CLASS
여러 JOB 그룹 관리
WINDOW
특정 시간대 실행

JOB (작업)

스케줄러에서 실행되는 최상위 작업 단위
JOB은 스케줄러에서 실행되는 최상위 작업 단위 입니다. JOB 하나에 "무엇을", "언제", "어떻게" 실행할지 모두 정의할 수 있습니다. 대부분의 경우 JOB만 생성하면 충분하며, PROGRAM이나 SCHEDULE을 별도로 만들 필요가 없습니다. JOB은 프로시저 호출, PL/SQL 블록 실행, 외부 프로그램 실행 등 다양한 작업을 수행할 수 있으며, 실행 주기, 시작 시간, 반복 패턴 등을 직접 설정할 수 있습니다. 스케줄러의 핵심 요소입니다.

PROGRAM (프로그램)

실행 로직을 별도로 정의한 객체
PROGRAM은 "무엇을 실행할지"에 대한 로직을 별도로 정의한 객체입니다. 여러 JOB에서 동일한 작업 로직을 재사용해야 할 때 유용합니다. 예를 들어, 같은 프로시저를 여러 시간대에 실행해야 한다면, PROGRAM으로 프로시저를 정의하고 각 JOB에서 이를 참조할 수 있습니다. PROGRAM은 프로시저명, PL/SQL 블록, 외부 실행 파일 등을 지정할 수 있으며, 인자(argument)도 정의 가능합니다. 하지만 단순한 작업이라면 JOB에 직접 작성하는 것이 더 간단합니다.

SCHEDULE (스케줄)

시간 패턴을 별도로 정의한 객체
SCHEDULE은 "언제 실행할지"에 대한 시간 패턴을 별도로 정의한 객체입니다. 복잡한 실행 주기를 여러 JOB에서 공유해야 할 때 사용합니다. 예를 들어, "매주 월요일 오전 9시"라는 스케줄을 SCHEDULE로 만들어두면, 여러 JOB에서 이를 참조할 수 있습니다. SCHEDULE에는 시작 시간, 반복 간격, 종료 시간 등을 설정할 수 있으며, Calendar 표현식을 사용합니다. 하지만 대부분의 경우 JOB의 repeat_interval에 직접 작성하는 것이 더 직관적입니다.

JOB CLASS (작업 클래스)

여러 JOB을 그룹으로 묶어 관리하는 컨테이너
JOB CLASS는 여러 JOB을 그룹으로 묶어 관리하는 컨테이너입니다. 같은 종류의 JOB들을 하나의 클래스로 분류하여 리소스 할당, 우선순위 설정, 로깅 정책 등을 통합 관리할 수 있습니다. 예를 들어, 백업 관련 JOB들을 "BACKUP_CLASS"로 묶으면, 이 클래스에 속한 모든 JOB의 실행 우선순위를 한 번에 조정할 수 있습니다. 대규모 시스템에서 수십 개의 JOB을 관리할 때 유용하지만, 소규모 프로젝트에서는 거의 사용하지 않습니다.

WINDOW (윈도우)

특정 시간대에만 작업을 실행하도록 제한하는 시간 구간 정의 객체
WINDOW는 특정 시간대를 정의하여, 그 시간 동안만 JOB을 실행하도록 제한하는 기능입니다. 예를 들어, "야간 배치 윈도우(23:00~06:00)"를 만들면, 이 시간대에만 배치 작업이 실행되도록 설정할 수 있습니다. WINDOW는 시작/종료 시간, 반복 패턴, 리소스 플랜 등을 포함할 수 있으며, 시스템 부하가 적은 시간대를 활용하여 무거운 작업을 처리할 때 사용됩니다. 일반적인 개발 환경에서는 거의 사용하지 않으며, DBA가 시스템 자원 관리를 위해 활용합니다.

스케줄러 JOB 기본 구조

BEGIN DBMS_SCHEDULER.CREATE_JOB ( job_name => 'job_이름', job_type => 'STORED_PROCEDURE' 또는 'PLSQL_BLOCK', job_action => '프로시저/PLSQL 코드', start_date => SYSTIMESTAMP, repeat_interval => 'FREQ=...; INTERVAL=...;', enabled => TRUE ); END; /
SQL
복사

repeat_interval (주기 설정) 문법

오라클의 스케줄러는 캘린더(Calendar) 문법을 사용한다.

● 매 4초마다 실행

FREQ=SECONDLY; INTERVAL=4
Plain Text
복사

● 매일 오전 3시 실행

FREQ=DAILY; BYHOUR=3; BYMINUTE=0; BYSECOND=0
Plain Text
복사

● 매 5분마다 실행

FREQ=MINUTELY; INTERVAL=5
Plain Text
복사

● 매 월요일 09시 실행

FREQ=WEEKLY; BYDAY=MON; BYHOUR=9
Plain Text
복사

프로시저 기반 스케줄러 예제

CREATE OR REPLACE PROCEDURE proc_test IS BEGIN INSERT INTO log_table (msg, created_at) VALUES ('자동 실행', SYSDATE); END; / BEGIN DBMS_SCHEDULER.CREATE_JOB ( job_name => 'job_test', job_type => 'STORED_PROCEDURE', job_action => 'proc_test', start_date => SYSTIMESTAMP, repeat_interval => 'FREQ=SECONDLY; INTERVAL=4', enabled => TRUE ); END; /
SQL
복사

코드 해설

프로시저 생성 부분

CREATE OR REPLACE PROCEDURE proc_test IS BEGIN INSERT INTO log_table (msg, created_at) VALUES ('자동 실행', SYSDATE); END; /
SQL
복사
CREATE OR REPLACE PROCEDURE proc_test: proc_test라는 프로시저를 생성합니다. 이미 존재하면 덮어씁니다.
INSERT INTO log_table: log_table 테이블에 데이터를 삽입합니다.
VALUES ('자동 실행', SYSDATE): '자동 실행'이라는 메시지와 현재 시간을 기록합니다.
이 프로시저는 실행될 때마다 로그 테이블에 한 줄씩 기록을 남깁니다.

스케줄러 JOB 생성 부분

BEGIN DBMS_SCHEDULER.CREATE_JOB ( job_name => 'job_test', job_type => 'STORED_PROCEDURE', job_action => 'proc_test', start_date => SYSTIMESTAMP, repeat_interval => 'FREQ=SECONDLY; INTERVAL=4', enabled => TRUE ); END; /
SQL
복사
job_name => 'job_test': JOB의 이름을 job_test로 지정합니다.
job_type => 'STORED_PROCEDURE': 이 JOB은 저장 프로시저를 실행하는 타입입니다.
job_action => 'proc_test': 실행할 프로시저 이름을 지정합니다. 위에서 만든 proc_test 프로시저가 실행됩니다.
start_date => SYSTIMESTAMP: JOB이 즉시 시작됩니다 (현재 시각부터).
repeat_interval => 'FREQ=SECONDLY; INTERVAL=4': 4초마다 반복 실행됩니다.
FREQ=SECONDLY: 초 단위로 실행
INTERVAL=4: 4초마다 반복
enabled => TRUE: JOB을 생성과 동시에 활성화합니다. FALSE로 설정하면 생성만 하고 실행하지 않습니다.

실행 결과

이 코드를 실행하면 4초마다 proc_test 프로시저가 자동으로 실행됩니다.
log_table 테이블에 4초 간격으로 '자동 실행' 로그가 계속 쌓입니다.
JOB을 중지하려면 DBMS_SCHEDULER.DISABLE('job_test')를 실행하거나 삭제해야 합니다.

PL/SQL 블록 기반 스케줄러 예제

BEGIN DBMS_SCHEDULER.CREATE_JOB ( job_name => 'job_block_test', job_type => 'PLSQL_BLOCK', job_action => 'BEGIN INSERT INTO test VALUES (SYSDATE); END;', start_date => SYSTIMESTAMP, repeat_interval => 'FREQ=MINUTELY; INTERVAL=1', enabled => TRUE ); END; /
SQL
복사

코드 해설

JOB 생성 구조

BEGIN DBMS_SCHEDULER.CREATE_JOB ( job_name => 'job_block_test', job_type => 'PLSQL_BLOCK', job_action => 'BEGIN INSERT INTO test VALUES (SYSDATE); END;', start_date => SYSTIMESTAMP, repeat_interval => 'FREQ=MINUTELY; INTERVAL=1', enabled => TRUE ); END; /
SQL
복사
job_name => 'job_block_test': JOB의 이름을 job_block_test로 지정합니다.
job_type => 'PLSQL_BLOCK': 이 JOB은 PL/SQL 블록을 직접 실행하는 타입입니다. 프로시저를 따로 만들지 않고 코드를 바로 실행할 수 있습니다.
job_action => 'BEGIN INSERT INTO test VALUES (SYSDATE); END;': 실행할 PL/SQL 코드를 문자열로 직접 작성합니다. 이 코드는 test 테이블에 현재 시간(SYSDATE)을 삽입합니다.
start_date => SYSTIMESTAMP: JOB이 즉시 시작됩니다 (현재 시각부터).
repeat_interval => 'FREQ=MINUTELY; INTERVAL=1': 1분마다 반복 실행됩니다.
FREQ=MINUTELY: 분 단위로 실행
INTERVAL=1: 1분마다 반복
enabled => TRUE: JOB을 생성과 동시에 활성화합니다.

STORED_PROCEDURE vs PLSQL_BLOCK 비교

구분
STORED_PROCEDURE
PLSQL_BLOCK
프로시저 필요
필요 (미리 생성)
불필요
코드 위치
프로시저명만 지정
코드를 직접 작성
재사용성
높음 (여러 곳에서 호출 가능)
낮음 (해당 JOB에만 사용)
유지보수
프로시저 수정 시 반영
JOB 수정 필요
적합한 경우
복잡한 로직, 재사용 필요
간단한 작업, 일회성

실행 결과

이 코드를 실행하면 1분마다 test 테이블에 현재 시간이 자동으로 삽입됩니다.
프로시저를 따로 만들지 않아도 되므로 간단한 작업에 유용합니다.
JOB을 중지하려면 DBMS_SCHEDULER.DISABLE('job_block_test')를 실행하거나 삭제해야 합니다.

사용 팁

간단한 INSERT/UPDATE는 PLSQL_BLOCK이 편리합니다.
복잡한 로직이나 반복 사용이 필요하면 STORED_PROCEDURE를 사용하세요.
PLSQL_BLOCK 내부에서 COMMIT;을 명시적으로 작성해야 트랜잭션이 완료됩니다.

스케줄러 확인

● JOB 목록 조회

SELECT job_name, enabled, state, last_start_date, next_run_date FROM user_scheduler_jobs;
SQL
복사

● JOB 실행 로그

SELECT log_date, status, error#, job_name FROM user_scheduler_job_run_details ORDER BY log_date DESC;
SQL
복사

JOB 제어

● 비활성화

BEGIN DBMS_SCHEDULER.DISABLE('job_test'); END; /
SQL
복사

● 활성화

BEGIN DBMS_SCHEDULER.ENABLE('job_test'); END; /
SQL
복사

● 삭제

BEGIN DBMS_SCHEDULER.DROP_JOB('job_test'); END; /
SQL
복사

스케줄러 사용 시 주의사항

매우 짧은 주기(1초)는 DB 부담 증가
실패한 JOB은 BROKEN 상태로 전환될 수 있음 (로그 확인 필수)
트리거와 다르게 트랜잭션과 독립적으로 실행됨
시스템 리소스를 계속 사용하므로 과도한 잡 생성 주의

트리거 vs 스케줄러 비교

구분
트리거
스케줄러
실행 조건
DML 사건 발생
시간 기반 실행
실행 시점
BEFORE / AFTER
특정 시각 또는 반복
주기 실행
불가
가능
주 사용 목적
데이터 무결성, 로그
정시 작업, 자동화

파일 테이블 자동 정리 스케줄러 예제

1분마다 등록된 지 5분이 지난 파일 정보를 자동으로 삭제하는 스케줄러
주의: 이 스케줄러는 데이터베이스의 파일 정보만 삭제합니다. 실제 파일 시스템에 저장된 물리적 파일은 별도의 스케줄러나 외부 프로그램으로 삭제해야 합니다.

파일 테이블 생성

CREATE TABLE files ( file_id NUMBER PRIMARY KEY, file_name VARCHAR2(200), created_date DATE DEFAULT SYSDATE );
SQL
복사

파일 삭제 프로시저 생성

CREATE OR REPLACE PROCEDURE proc_delete_old_files IS BEGIN -- 5분 이상 지난 파일 삭제 DELETE FROM files WHERE created_date <= SYSDATE - INTERVAL '5' MINUTE; COMMIT; END; /
SQL
복사

스케줄러 생성 (1분마다 실행)

BEGIN DBMS_SCHEDULER.CREATE_JOB ( job_name => 'job_delete_old_files', job_type => 'STORED_PROCEDURE', job_action => 'proc_delete_old_files', start_date => SYSTIMESTAMP, repeat_interval => 'FREQ=MINUTELY; INTERVAL=1', enabled => TRUE ); END; /
SQL
복사

코드 해설

job_name => 'job_delete_old_files': JOB 이름을 job_delete_old_files로 지정합니다.
job_type => 'STORED_PROCEDURE': 프로시저를 실행하는 타입입니다.
job_action => 'proc_delete_old_files': 실행할 프로시저 이름을 지정합니다.
start_date => SYSTIMESTAMP: 즉시 시작됩니다.
repeat_interval => 'FREQ=MINUTELY; INTERVAL=1': 1분마다 반복 실행됩니다.
enabled => TRUE: 생성과 동시에 활성화됩니다.

PL/SQL 블록으로 구현 (프로시저 없이)

BEGIN DBMS_SCHEDULER.CREATE_JOB ( job_name => 'job_delete_old_files_block', job_type => 'PLSQL_BLOCK', job_action => 'BEGIN DELETE FROM files WHERE created_date <= SYSDATE - INTERVAL ''5'' MINUTE; COMMIT; END;', start_date => SYSTIMESTAMP, repeat_interval => 'FREQ=MINUTELY; INTERVAL=1', enabled => TRUE ); END; /
SQL
복사

실행 결과

이 스케줄러는 1분마다 자동으로 실행됩니다.
files 테이블에서 등록된 지 5분이 지난 파일 정보를 자동으로 삭제합니다.
created_date <= SYSDATE - INTERVAL '5' MINUTE 조건으로 5분 이상 지난 데이터를 찾아 삭제합니다.

테스트 방법

-- 테스트 데이터 삽입 INSERT INTO files VALUES (1, 'test1.txt', SYSDATE - INTERVAL '6' MINUTE); INSERT INTO files VALUES (2, 'test2.txt', SYSDATE - INTERVAL '3' MINUTE); INSERT INTO files VALUES (3, 'test3.txt', SYSDATE); COMMIT; -- 1분 후 확인 (6분 지난 파일만 삭제되어야 함) SELECT * FROM files;
SQL
복사

JOB 제어

중지:
BEGIN DBMS_SCHEDULER.DISABLE('job_delete_old_files'); END; /
SQL
복사
재시작:
BEGIN DBMS_SCHEDULER.ENABLE('job_delete_old_files'); END; /
SQL
복사
삭제:
BEGIN DBMS_SCHEDULER.DROP_JOB('job_delete_old_files'); END; /
SQL
복사