Oracle には 2 種類のジョブスケジューラが存在します。DBMS_JOB(Oracle 7 以降の旧スケジューラ)とDBMS_SCHEDULER(Oracle 10g 以降の新スケジューラ)です。
DBMS_JOB は機能が限定的なためオラクル社は DBMS_SCHEDULER への移行を推奨しています。しかし既存のレガシーシステムでは DBMS_JOB が今も多く使われており、運用・保守のために理解が必要です。
この記事でわかること
- DBMS_JOB の仕組みと DBMS_SCHEDULER との違い
- DBMS_JOB.SUBMIT でジョブを登録する方法
- interval パラメータの設定(毎日・毎時・特定曜日など)
- DBMS_JOB.CHANGE / NEXT_DATE / INTERVAL でジョブを変更する方法
- DBMS_JOB.BROKEN でジョブを無効化する方法
- USER_JOBS / DBA_JOBS でジョブを管理・確認する方法
- DBMS_SCHEDULER への移行方法
DBMS_JOB と DBMS_SCHEDULER の比較
| 項目 | DBMS_JOB | DBMS_SCHEDULER |
|---|---|---|
| 導入バージョン | Oracle 7 以降 | Oracle 10g 以降 |
| スケジュール | PL/SQL 式(interval パラメータ) | カレンダー文字列・スケジュールオブジェクト |
| 実行ログ | USER_JOBS.FAILURES / WHAT | USER_SCHEDULER_JOB_LOG(詳細なログ) |
| 実行ユーザー | ジョブ作成者のスキーマ | ジョブ名・所有者を分離できる |
| 外部プログラム | PL/SQL のみ | PL/SQL・外部実行ファイル・DB スクリプト |
| 依存関係 | なし | チェーンで依存関係を定義可能 |
| 推奨度 | 非推奨(レガシー) | 推奨(現在のスタンダード) |
DBMS_JOB.SUBMIT でジョブを登録する
DBMS_JOB.SUBMIT の基本的な使い方
DECLARE
v_job NUMBER;
BEGIN
DBMS_JOB.SUBMIT(
job => v_job, -- 出力: 割り当てられたジョブ番号
what => 'process_monthly_sales;', -- 実行する PL/SQL 文(セミコロン必須)
next_date => SYSDATE, -- 最初の実行日時(即時実行は SYSDATE)
interval => 'SYSDATE + 1/24', -- 実行間隔(次の実行日時を計算する PL/SQL 式)
no_parse => FALSE -- FALSE: 登録時に what の構文チェックを行う
);
COMMIT; -- DBMS_JOB.SUBMIT は COMMIT して初めて登録が確定する
DBMS_OUTPUT.PUT_LINE('ジョブ番号: ' || v_job);
END;
/
interval パラメータのよく使うパターン
-- interval パラメータは「次回の実行日時を返す PL/SQL 式」を文字列で指定する -- 式の中では SYSDATE が「前回の実行完了時刻」を表す -- 毎日同じ時刻に実行(毎日午前 2 時) interval => 'TRUNC(SYSDATE + 1) + 2/24' -- 毎時 0 分に実行(1 時間ごと) interval => 'TRUNC(SYSDATE, ''HH24'') + 1/24' -- 毎週月曜日の午前 1 時に実行 interval => 'NEXT_DAY(TRUNC(SYSDATE), ''MONDAY'') + 1/24' -- 毎月 1 日の午前 0 時に実行 interval => 'ADD_MONTHS(TRUNC(SYSDATE, ''MM''), 1)' -- 10 分ごとに実行 interval => 'SYSDATE + 10/1440' -- 1 回だけ実行(interval を NULL にするとジョブは自動削除される) interval => NULL -- 実行しない(BROKEN=TRUE)にする場合は interval を設定したまま BROKEN にする
ジョブを変更・停止する
DBMS_JOB.CHANGE / BROKEN / NEXT_DATE / INTERVAL
-- ジョブの設定をまとめて変更する(NULL は変更しない)
BEGIN
DBMS_JOB.CHANGE(
job => 42, -- ジョブ番号
what => 'process_weekly_report;', -- 新しい実行内容(NULL で変更しない)
next_date => SYSDATE + 1, -- 次の実行日時
interval => 'SYSDATE + 7' -- 新しい間隔(1 週間)
);
COMMIT;
END;
/
-- 次の実行日時だけ変更する
BEGIN
DBMS_JOB.NEXT_DATE(
job => 42,
next_date => TRUNC(SYSDATE + 1) + 3/24 -- 翌日 3 時
);
COMMIT;
END;
/
-- 実行間隔だけ変更する
BEGIN
DBMS_JOB.INTERVAL(
job => 42,
interval => 'SYSDATE + 1/24' -- 毎時間に変更
);
COMMIT;
END;
/
-- ジョブを一時停止する(BROKEN=TRUE でジョブが実行されなくなる)
BEGIN
DBMS_JOB.BROKEN(
job => 42,
broken => TRUE, -- TRUE: 停止 / FALSE: 再開
next_date => SYSDATE + 1 -- 再開時の次の実行日時
);
COMMIT;
END;
/
-- ジョブを手動で即時実行する
BEGIN
DBMS_JOB.RUN(42);
END;
/
-- ジョブを削除する
BEGIN
DBMS_JOB.REMOVE(42);
COMMIT;
END;
/
USER_JOBS / DBA_JOBS でジョブを管理する
USER_JOBS でジョブを確認する
-- 自分のジョブを確認する
SELECT
job,
what, -- 実行する PL/SQL 文
next_date, -- 次回実行予定日時
TO_CHAR(next_date, 'YYYY-MM-DD HH24:MI:SS') AS next_run,
interval, -- 実行間隔式
broken, -- Y: 停止中, N: 有効
failures, -- 連続失敗回数(16 回でBROKEN=Yに自動変更)
last_date, -- 最終実行日時
last_sec, -- 最終実行時刻
total_time -- 合計実行時間(秒)
FROM USER_JOBS
ORDER BY job;
-- DBA_JOBS(DBA 権限が必要): 全ユーザーのジョブを確認する
SELECT
job, log_user, priv_user, schema_user,
what, next_date, interval, broken, failures
FROM DBA_JOBS
ORDER BY log_user, job;
-- 現在実行中のジョブを確認する(DBA 権限が必要)
SELECT
j.job,
j.log_user,
j.what,
s.sid,
s.serial#,
s.username
FROM DBA_JOBS_RUNNING j
JOIN V$SESSION s ON j.sid = s.sid;
DBMS_SCHEDULER への移行方法
DBMS_JOB から DBMS_SCHEDULER へ移行する
-- DBMS_JOB のジョブ(毎日午前 2 時実行)を DBMS_SCHEDULER に移行する例
-- 移行前(DBMS_JOB)
-- DBMS_JOB.SUBMIT(v_job, 'process_monthly_sales;',
-- SYSDATE, 'TRUNC(SYSDATE + 1) + 2/24');
-- 移行後(DBMS_SCHEDULER)
BEGIN
DBMS_SCHEDULER.CREATE_JOB(
job_name => 'MONTHLY_SALES_JOB',
job_type => 'STORED_PROCEDURE',
job_action => 'PROCESS_MONTHLY_SALES',
start_date => SYSTIMESTAMP,
repeat_interval => 'FREQ=DAILY; BYHOUR=2; BYMINUTE=0',
enabled => TRUE,
comments => '月次売上集計(DBMS_JOBからの移行)'
);
END;
/
-- DBMS_SCHEDULER のジョブ実行ログを確認する(詳細なログが取れる)
SELECT
job_name,
status,
run_duration,
actual_start_date,
error#,
additional_info
FROM USER_SCHEDULER_JOB_RUN_DETAILS
WHERE job_name = 'MONTHLY_SALES_JOB'
ORDER BY actual_start_date DESC
FETCH FIRST 10 ROWS ONLY;
まとめ
- DBMS_JOB.SUBMIT:what(実行内容)・next_date(初回実行)・interval(次回実行を返すPL/SQL式)を指定してジョブを登録する。COMMIT が必要
- interval の NULL:NULL にすると 1 回だけ実行して自動削除される
- BROKEN:TRUE にするとジョブが実行されなくなる。16 回連続失敗でも自動的に BROKEN=Y になる
- USER_JOBS.failures:連続失敗回数。0 に戻すには DBMS_JOB.BROKEN(job, FALSE) で再有効化する
- 新規開発は DBMS_SCHEDULER を使う:詳細ログ・外部プログラム実行・チェーンなど機能が充実している
DBMS_SCHEDULER の詳細については DBMS_SCHEDULER完全ガイドを参照してください。PRAGMA AUTONOMOUS_TRANSACTION を使ったジョブのエラーログ記録は PRAGMA AUTONOMOUS_TRANSACTION完全ガイドも参照してください。