OracleのDBMS_SCHEDULERでジョブを自動実行する方法【バッチ処理完全ガイド】

当ページのリンクには広告が含まれています。

「毎日深夜0時にバッチを動かしたい」「月次集計を自動化したい」——OracleにはDBMS_SCHEDULERというDB内蔵のジョブスケジューラがあります。本記事では基本的なジョブ作成から確認・実行・削除まで解説します。

目次

1. DBMS_SCHEDULERとは(DBMS_JOBとの違い) {#about}

比較項目DBMS_JOB(旧)DBMS_SCHEDULER(新)
導入バージョンOracle 7〜Oracle 10g〜
スケジュール書式interval式(例:SYSDATE+1カレンダー式・CRON互換
外部スクリプト不可OSコマンド・シェルスクリプト実行可能
ログ・監視限定的詳細なログ・アラート対応
推奨非推奨(旧機能)現在の標準

本記事はDBMS_SCHEDULERを対象とします。


2. ジョブを作成する(CREATE_JOB) {#create-job}

PL/SQLブロックを実行するジョブ

BEGIN
    DBMS_SCHEDULER.CREATE_JOB(
        job_name        => 'JOB_DAILY_STATS',           -- ジョブ名(大文字推奨)
        job_type        => 'PLSQL_BLOCK',               -- PL/SQLブロックを実行
        job_action      => 'BEGIN update_daily_stats; END;',  -- 実行するPL/SQL
        start_date      => SYSTIMESTAMP,                -- 開始日時
        repeat_interval => 'FREQ=DAILY; BYHOUR=0; BYMINUTE=0; BYSECOND=0',  -- 毎日0:00
        end_date        => NULL,                        -- 終了日時(NULLは無期限)
        enabled         => TRUE,                        -- 作成と同時に有効化
        comments        => '毎日0時に日次統計更新を実行'
    );
END;
/

ストアドプロシージャを実行するジョブ

BEGIN
    DBMS_SCHEDULER.CREATE_JOB(
        job_name        => 'JOB_MONTHLY_REPORT',
        job_type        => 'STORED_PROCEDURE',          -- ストアドプロシージャを実行
        job_action      => 'SCOTT.GENERATE_MONTHLY_REPORT',  -- スキーマ名.プロシージャ名
        repeat_interval => 'FREQ=MONTHLY; BYMONTHDAY=1; BYHOUR=2; BYMINUTE=0',  -- 毎月1日2:00
        enabled         => TRUE,
        comments        => '毎月1日2時に月次レポートを生成'
    );
END;
/

OSコマンド・シェルスクリプトを実行するジョブ

BEGIN
    DBMS_SCHEDULER.CREATE_JOB(
        job_name        => 'JOB_SHELL_BACKUP',
        job_type        => 'EXECUTABLE',                -- OSコマンドを実行
        job_action      => '/opt/oracle/scripts/backup.sh',  -- スクリプトのフルパス
        repeat_interval => 'FREQ=DAILY; BYHOUR=3; BYMINUTE=0',
        enabled         => TRUE,
        comments        => '毎日3時にバックアップスクリプトを実行'
    );
END;
/

3. ジョブの確認 {#check-job}

登録済みジョブの一覧

-- 自分のジョブを確認
SELECT
    JOB_NAME,
    JOB_TYPE,
    ENABLED,
    STATE,
    LAST_START_DATE,
    LAST_RUN_DURATION,
    NEXT_RUN_DATE,
    RUN_COUNT,
    FAILURE_COUNT
FROM USER_SCHEDULER_JOBS
ORDER BY JOB_NAME;

STATEの値:

STATE意味
SCHEDULED次回実行待ち(正常)
RUNNING現在実行中
DISABLED無効化されている
CHAIN_STALLEDチェーンがスタック
-- 全ユーザーのジョブを確認(DBA権限)
SELECT OWNER, JOB_NAME, STATE, NEXT_RUN_DATE, FAILURE_COUNT
FROM DBA_SCHEDULER_JOBS
ORDER BY OWNER, JOB_NAME;

現在実行中のジョブを確認

SELECT JOB_NAME, SESSION_ID, RUNNING_INSTANCE, ELAPSED_TIME
FROM USER_SCHEDULER_RUNNING_JOBS;

4. ジョブの手動実行・一時停止・削除 {#manage-job}

ジョブを今すぐ手動実行する

-- 即時実行(次回スケジュールには影響しない)
BEGIN
    DBMS_SCHEDULER.RUN_JOB('JOB_DAILY_STATS');
END;
/

ジョブを有効化・無効化

-- 無効化(スケジュール実行を止める)
BEGIN
    DBMS_SCHEDULER.DISABLE('JOB_DAILY_STATS');
END;
/

-- 有効化
BEGIN
    DBMS_SCHEDULER.ENABLE('JOB_DAILY_STATS');
END;
/

ジョブの設定を変更

-- スケジュールを変更
BEGIN
    DBMS_SCHEDULER.SET_ATTRIBUTE(
        name      => 'JOB_DAILY_STATS',
        attribute => 'REPEAT_INTERVAL',
        value     => 'FREQ=DAILY; BYHOUR=1; BYMINUTE=0'  -- 1:00に変更
    );
END;
/

-- コメントを変更
BEGIN
    DBMS_SCHEDULER.SET_ATTRIBUTE(
        name      => 'JOB_DAILY_STATS',
        attribute => 'COMMENTS',
        value     => '毎日1時に日次統計更新を実行(変更済み)'
    );
END;
/

ジョブを削除

BEGIN
    DBMS_SCHEDULER.DROP_JOB('JOB_DAILY_STATS');
END;
/

-- 実行中でも強制削除
BEGIN
    DBMS_SCHEDULER.DROP_JOB(
        job_name => 'JOB_DAILY_STATS',
        force    => TRUE
    );
END;
/

5. プログラムとスケジュールを分けて管理する {#program-schedule}

同じロジックを複数のスケジュールで使い回したい場合、「プログラム」と「スケジュール」を分けて定義できます。

-- プログラムの作成(処理内容)
BEGIN
    DBMS_SCHEDULER.CREATE_PROGRAM(
        program_name    => 'PROG_DAILY_STATS',
        program_type    => 'STORED_PROCEDURE',
        program_action  => 'SCOTT.UPDATE_DAILY_STATS',
        enabled         => TRUE,
        comments        => '日次統計更新プロシージャ'
    );
END;
/

-- スケジュールの作成(実行タイミング)
BEGIN
    DBMS_SCHEDULER.CREATE_SCHEDULE(
        schedule_name   => 'SCH_EVERY_MIDNIGHT',
        repeat_interval => 'FREQ=DAILY; BYHOUR=0; BYMINUTE=0; BYSECOND=0',
        comments        => '毎日0時'
    );
END;
/

-- プログラムとスケジュールを組み合わせたジョブを作成
BEGIN
    DBMS_SCHEDULER.CREATE_JOB(
        job_name     => 'JOB_DAILY_STATS_V2',
        program_name => 'PROG_DAILY_STATS',
        schedule_name => 'SCH_EVERY_MIDNIGHT',
        enabled      => TRUE
    );
END;
/

6. スケジュールの設定パターン(CRON互換) {#cron}

やりたいことREPEAT_INTERVAL
毎日0時FREQ=DAILY; BYHOUR=0; BYMINUTE=0; BYSECOND=0
毎時0分FREQ=HOURLY; BYMINUTE=0; BYSECOND=0
毎週月曜日の9時FREQ=WEEKLY; BYDAY=MON; BYHOUR=9; BYMINUTE=0
毎月1日の3時FREQ=MONTHLY; BYMONTHDAY=1; BYHOUR=3; BYMINUTE=0
毎月末日の2時FREQ=MONTHLY; BYMONTHDAY=-1; BYHOUR=2; BYMINUTE=0
平日(月〜金)の8時FREQ=DAILY; BYDAY=MON,TUE,WED,THU,FRI; BYHOUR=8
30分ごとFREQ=MINUTELY; INTERVAL=30
-- 次回実行日時を確認してスケジュールが正しいか検証
SELECT DBMS_SCHEDULER.EVALUATE_CALENDAR_STRING(
    'FREQ=WEEKLY; BYDAY=MON; BYHOUR=9; BYMINUTE=0',
    NULL, SYSTIMESTAMP
) AS 次回実行日時
FROM DUAL;

7. ジョブ実行ログの確認 {#log}

-- ジョブの実行履歴ログ
SELECT
    JOB_NAME,
    STATUS,
    ACTUAL_START_DATE,
    RUN_DURATION,
    ADDITIONAL_INFO
FROM USER_SCHEDULER_JOB_LOG
WHERE JOB_NAME = 'JOB_DAILY_STATS'
ORDER BY ACTUAL_START_DATE DESC
FETCH FIRST 10 ROWS ONLY;

STATUSの値:

STATUS意味
SUCCEEDED正常終了
FAILEDエラー終了
STOPPED手動停止
-- エラーの詳細を確認
SELECT JOB_NAME, ERROR# AS エラーコード, ADDITIONAL_INFO AS エラー詳細
FROM USER_SCHEDULER_JOB_LOG
WHERE STATUS = 'FAILED'
ORDER BY ACTUAL_START_DATE DESC;

8. よくあるエラーと対処 {#errors}

ORA-27486:権限不足

ORA-27486: 不十分な特権です
-- DBMS_SCHEDULERの実行権限を付与
GRANT CREATE JOB TO SCOTT;
GRANT MANAGE SCHEDULER TO SCOTT;  -- ジョブ管理全般

ジョブがFAILEDになる

-- エラー詳細を確認
SELECT ADDITIONAL_INFO FROM USER_SCHEDULER_JOB_LOG
WHERE JOB_NAME = 'JOB_DAILY_STATS' AND STATUS = 'FAILED'
ORDER BY ACTUAL_START_DATE DESC;

プロシージャ名のスペルミスやスキーマ名の未指定が多い原因です。

ジョブが実行されない(DISABLED状態)

-- 有効化されているか確認
SELECT ENABLED FROM USER_SCHEDULER_JOBS WHERE JOB_NAME = 'JOB_DAILY_STATS';

-- 有効化する
EXEC DBMS_SCHEDULER.ENABLE('JOB_DAILY_STATS');

9. まとめ:ジョブ管理チェックリスト {#summary}

作成時
□ ジョブ名は大文字・わかりやすい命名規則で統一
□ 作成後に RUN_JOB で手動実行して動作確認
□ EVALUATE_CALENDAR_STRING でスケジュールの次回実行日時を確認

運用時
□ USER_SCHEDULER_JOB_LOG を定期確認(STATUS=FAILED がないか)
□ FAILURE_COUNT が増えていたら原因を調査
□ 不要になったジョブは DROP_JOB で削除(有効ジョブが増えると管理が困難)

トラブル時
□ 手動で RUN_JOB 実行 → 成功すれば認証・プロシージャの問題ではない
□ ADDITIONAL_INFO でエラー詳細を確認
□ STATE=DISABLED になっていたら ENABLE で再有効化

関連記事:

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

ITの事や自分の経験談など綴っていきたいと思っています。

コメント

コメントする

CAPTCHA


目次