Database Support Blog

  • Oracle Database
2022.01.14

Oracleのジョブ・チェーンを使用して複数処理を1つのジョブに登録する方法

Oracle Database では Oracle Scheduler を使用してジョブを実行させることが可能ですが、このジョブをOSのバッチファイルやジョブ管理ツールを利用せず、「ジョブの結果に基づいて他のジョブを実行したい」というお問い合わせをいただくことがあります。

今回はジョブの結果に基づいて後続の処理を実行させる方法として、Oracle Database のジョブ・チェーン機能を紹介します。


ジョブ・チェーン機能

ジョブ・チェーン機能では複数のジョブを1つのスケジューラジョブとして動作させることが出来ます。また、ジョブの結果により、次に実行するジョブを変化させるような条件分岐を含むことも出来ます。

例えば以下の図はジョブAのメイン処理を実行させ、正常に完了した場合のみ後続処理のジョブB、ジョブCを実行するという処理です。メイン処理のジョブAが失敗した場合はリカバリ処理のジョブDを実行させ、リカバリ処理の成功、失敗により実行させるジョブを変化させるといったジョブ・チェーンとなります。

上記条件分岐の場合、ジョブ・チェーンの設定例としては以下の通り、作成するステップは6つで、ルールは10個で制御できます。

【ステップ】

ステップ1

DBMS_SCHEDULER.DEFINE_CHAIN_STEP('my_chain1', 'step1','JOB_A');

ステップ2

DBMS_SCHEDULER.DEFINE_CHAIN_STEP('my_chain1', 'step2','JOB_B');

ステップ3

DBMS_SCHEDULER.DEFINE_CHAIN_STEP('my_chain1', 'step3','JOB_C');

ステップ4

DBMS_SCHEDULER.DEFINE_CHAIN_STEP('my_chain1', 'step4','JOB_D');

ステップ5

DBMS_SCHEDULER.DEFINE_CHAIN_STEP('my_chain1', 'step5','JOB_E');

ステップ6

DBMS_SCHEDULER.DEFINE_CHAIN_STEP('my_chain1', 'step6','JOB_F');


【ルール】

ルール


①-- Step1(JOB_A)は必ず実行(condition=>'TRUE')
DBMS_SCHEDULER.DEFINE_CHAIN_RULE('my_chain1', 'TRUE', 'START step1');

②-- -- Step1(JOB_A)が正常に完了した場合、Step2(JOB_B)を実行
DBMS_SCHEDULER.DEFINE_CHAIN_RULE('my_chain1', 'Step1 SUCCEEDED','Start Step2');

③-- Step1(JOB_A)でエラーが発生した場合、Step4(JOB_D)を実行
DBMS_SCHEDULER.DEFINE_CHAIN_RULE('my_chain1', 'Step1 FAILED','START step4');

④-- Step2(JOB_B)が正常に完了した場合、Step3(JOB_C)を実行
DBMS_SCHEDULER.DEFINE_CHAIN_RULE('my_chain1', 'Step2 SUCCEEDED','Start Step3');

⑤-- Step2(JOB_B)でエラーが発生した場合、終了へ
DBMS_SCHEDULER.DEFINE_CHAIN_RULE('my_chain1', 'Step2 FAILED','END');

⑥-- Step3(JOB_C)は処理が完了次第(成功/失敗に関わらず)チェーンを終了
DBMS_SCHEDULER.DEFINE_CHAIN_RULE('my_chain1', 'step3 COMPLETED', 'END');

⑦-- Step4(JOB_D)が正常に完了した場合、Step5(JOB_E)を実行
DBMS_SCHEDULER.DEFINE_CHAIN_RULE('my_chain1', 'Step4 SUCCEEDED','Start Step5');

⑧-- Step4(JOB_D)でエラーが発生した場合、Step6(JOB_F)を実行
DBMS_SCHEDULER.DEFINE_CHAIN_RULE('my_chain1', 'Step4 FAILED','START step6');

⑨-- Step5(JOB_E)は処理が完了次第(成功/失敗に関わらず)チェーンを終了
DBMS_SCHEDULER.DEFINE_CHAIN_RULE('my_chain1', 'step5 COMPLETED', 'END');

⑩-- Step6(JOB_F)は処理が完了次第(成功/失敗に関わらず)チェーンを終了
DBMS_SCHEDULER.DEFINE_CHAIN_RULE('my_chain1', 'step6 COMPLETED', 'END');


ジョブ・チェーンの作成

以下サンプルは前のプログラムが正常完了した場合は次のプログラムを実行し、失敗した場合はその時点で終了させる ジョブ・チェーン の作成例です。

(1). ジョブ・チェーンで使用するプログラムを作成

 
 SQL> BEGIN
   2  DBMS_SCHEDULER.CREATE_PROGRAM(
   3  program_name => 'TEST_PROGRAM1',
   4  program_type => 'PLSQL_BLOCK',
   5  program_action => 'BEGIN insert into test1 values(sysdate); END;',
   6  enabled => TRUE,
   7  comments => 'Program to insert using a PL/SQL block.');
   8  DBMS_SCHEDULER.enable (name => 'TEST_PROGRAM1');
   9  END;
  10  /
  
 PL/SQLプロシージャが正常に完了しました。
  
 SQL> BEGIN
   2  DBMS_SCHEDULER.CREATE_PROGRAM(
   3  program_name => 'TEST_PROGRAM2',
   4  program_type => 'PLSQL_BLOCK',
   5  program_action => 'BEGIN insert into test2 values(sysdate); END;',
   6  enabled => TRUE,
   7  comments => 'Program to insert using a PL/SQL block.');
   8  DBMS_SCHEDULER.enable (name => 'TEST_PROGRAM2');
   9  END;
  10  /
  
 PL/SQLプロシージャが正常に完了しました。
  
 SQL> BEGIN
   2  DBMS_SCHEDULER.CREATE_PROGRAM(
   3  program_name => 'TEST_PROGRAM3',
   4  program_type => 'PLSQL_BLOCK',
   5  program_action => 'BEGIN insert into test3 values(sysdate); END;',
   6  enabled => TRUE,
   7  comments => 'Program to insert using a PL/SQL block.');
   8  DBMS_SCHEDULER.enable (name => 'TEST_PROGRAM3');
   9  END;
  10  /
  
 PL/SQLプロシージャが正常に完了しました。
  
 SQL> BEGIN
   2  DBMS_SCHEDULER.CREATE_PROGRAM(
   3  program_name => 'TEST_PROGRAM4',
   4  program_type => 'PLSQL_BLOCK',
   5  program_action => 'BEGIN insert into test4 values(sysdate); END;',
   6  enabled => TRUE,
   7  comments => 'Program to insert using a PL/SQL block.');
   8  DBMS_SCHEDULER.enable (name => 'TEST_PROGRAM4');
   9  END;
  10  /
  
 PL/SQLプロシージャが正常に完了しました。
 

(2). チェーンの作成

 
 SQL> BEGIN
   2   DBMS_SCHEDULER.CREATE_CHAIN (
   3      chain_name           =>  'my_chain1',
   4      rule_set_name        =>  NULL,
   5      evaluation_interval  =>  NULL,
   6      comments             =>  NULL);
   7  END;
   8  /
  
 PL/SQLプロシージャが正常に完了しました。
 

(3). チェーンにステップ(プログラム)を追加

 
 SQL> BEGIN
   2   DBMS_SCHEDULER.DEFINE_CHAIN_STEP('my_chain1', 'step1','TEST_PROGRAM1');
   3   DBMS_SCHEDULER.DEFINE_CHAIN_STEP('my_chain1', 'step2','TEST_PROGRAM2');
   4   DBMS_SCHEDULER.DEFINE_CHAIN_STEP('my_chain1', 'step3','TEST_PROGRAM3');
   5   DBMS_SCHEDULER.DEFINE_CHAIN_STEP('my_chain1', 'step4','TEST_PROGRAM4');
   6  END;
   7  /
  
 PL/SQLプロシージャが正常に完了しました。
 

(4). チェーンのルールを追加

【設定するルール】



①TEST_PROGRAM1を実行。

②TEST_PROGRAM1が成功していればTEST_PROGRAM2を実行。
失敗していればこれ以降のジョブは実行しない。

③TEST_PROGRAM2が成功していればTEST_PROGRAM3を実行。
失敗していればこれ以降のジョブは実行しない。

④TEST_PROGRAM3が成功していればTEST_PROGRAM4を実行。
失敗していればこのジョブは実行しない。

 
 SQL> BEGIN
   2   -- step1(TEST_PROGRAM1)は必ず実行(condition=>'TRUE')
   3   DBMS_SCHEDULER.DEFINE_CHAIN_RULE('my_chain1', 'TRUE', 'START step1');
   4   -- ステップでエラーが発生した場合、チェーンを終了
   5   DBMS_SCHEDULER.DEFINE_CHAIN_RULE('my_chain1', 'Step1 FAILED','END');
   6   DBMS_SCHEDULER.DEFINE_CHAIN_RULE('my_chain1', 'Step2 FAILED','END');
   7   DBMS_SCHEDULER.DEFINE_CHAIN_RULE('my_chain1', 'Step3 FAILED','END');
   8   -- ステップが正常に完了した場合、次のステップを実行
   9   DBMS_SCHEDULER.DEFINE_CHAIN_RULE('my_chain1', 'Step1 SUCCEEDED','Start Step2');
  10   DBMS_SCHEDULER.DEFINE_CHAIN_RULE('my_chain1', 'Step2 SUCCEEDED','Start Step3');
  11   DBMS_SCHEDULER.DEFINE_CHAIN_RULE('my_chain1', 'Step3 SUCCEEDED','Start Step4');
  12   -- step4(TEST_PROGRAM4)は処理が完了次第(成功/失敗に関わらず)チェーンを終了
  13   DBMS_SCHEDULER.DEFINE_CHAIN_RULE('my_chain1', 'step4 COMPLETED', 'END');
  14  END;
  15  /
  
 PL/SQLプロシージャが正常に完了しました。
 

【参考情報】
条件構文の詳細については、以下マニュアルをご参照ください。

データベース管理者ガイド 19c F16141-06(原本部品番号:E96348-08) 2020年7月
- 29.6.5 チェーンへのルールの追加
  https://docs.oracle.com/cd/F19136_01/admin/scheduling-jobs-with-oracle-scheduler.html#GUID-5B924F0A-7E1A-4361-ADB4-F3F07CFC81EE

PL/SQLパッケージおよびタイプ・リファレンス 19c F16147-07(原本部品番号:E96430-11) 2020年5月
- 146.6.25 DEFINE_CHAIN_RULEプロシージャ
  https://docs.oracle.com/cd/F19136_01/arpls/DBMS_SCHEDULER.html#GUID-BF7D99FE-C33F-444E-8725-BBC24DD33027 


(5). チェーンの有効化

 
 SQL> BEGIN
   2  DBMS_SCHEDULER.ENABLE ('my_chain1');
   3  END;
   4  /
  
 PL/SQLプロシージャが正常に完了しました。
 

(6). ジョブ・チェーンを実行

 
 SQL> exec DBMS_SCHEDULER.RUN_CHAIN ('my_chain1','','test_my_chain1');
  
 PL/SQLプロシージャが正常に完了しました。
 

以下のようなジョブ・チェーンのスケジュールも可能です。

 
 SQL> begin
   2  DBMS_SCHEDULER.CREATE_JOB (job_name=>'test_my_chain1',
   3  job_type=>'CHAIN', job_action=>'my_chain1',
   4  repeat_interval=>'freq=daily;byhour=23;byminute=0;bysecond=0',
   5  enabled=>true);
   6  end;
   7  /
  
 PL/SQLプロシージャが正常に完了しました。
 

【補足情報】
*1 実行中のジョブ・チェーンの状況は *_SCHEDULER_RUNNING_CHAINS の情報から確認出来ます。

 
 SQL> select JOB_NAME,CHAIN_NAME,STEP_NAME,STATE,ERROR_CODE,COMPLETED
   2  from USER_SCHEDULER_RUNNING_CHAINS order by STEP_NAME;
  
 JOB_NAME          CHAIN_NAME     STEP_NAME     STATE           ERROR_CODE    COMPL
 ----------------- -------------- ------------- -------------- -------------- -----------
 TEST_MY_CHAIN1    MY_CHAIN1      STEP1         SUCCEEDED                   0 TRUE
 TEST_MY_CHAIN1    MY_CHAIN1      STEP2         SUCCEEDED                   0 TRUE
 TEST_MY_CHAIN1    MY_CHAIN1      STEP3         RUNNING                       FALSE
 TEST_MY_CHAIN1    MY_CHAIN1      STEP4         NOT_STARTED                   FALSE
 

*2 ジョブの完了後は *_SCHEDULER_RUNNING_CHAINS の情報は確認出来ないため、実行後の履歴は *_SCHEDULER_JOB_RUN_DETAILS より確認可能です。

 
 SQL> select JOB_NAME,JOB_SUBNAME,STATUS,ERROR#,ACTUAL_START_DATE
   2  from USER_SCHEDULER_JOB_RUN_DETAILS order by ACTUAL_START_DATE;
  
 JOB_NAME           JOB_SUBNAM     STATUS         ERROR#      ACTUAL_START_DATE
 ------------------ -------------- ------------ ------------- ----------------------------------
 TEST_MY_CHAIN1                    SUCCEEDED                0 21-02-06 00:50:17.824665 ASIA/TOKYO
 TEST_MY_CHAIN1     STEP1          SUCCEEDED                0 21-02-06 00:50:17.950740 ASIA/TOKYO
 TEST_MY_CHAIN1     STEP2          SUCCEEDED                0 21-02-06 00:50:18.064066 ASIA/TOKYO
 TEST_MY_CHAIN1     STEP3          FAILED                6550 21-02-06 00:50:18.168103 ASIA/TOKYO
 

上記例では STEP3 で ORA-06550 のエラーを受けて失敗しています。エラーの詳細は同ディクショナリビューの ERRORS 列からも確認できます。

 
 SQL> select JOB_NAME,JOB_SUBNAME,STATUS,ERROR#,ERRORS
   2  from user_SCHEDULER_JOB_RUN_DETAILS WHERE ERROR# = '6550';
  
 JOB_NAME         JOB_SUBNAM     STATUS    ERROR#     ERRORS
 ---------------- -------------- --------- ---------- -------------------------------------------------
 TEST_MY_CHAIN1   STEP3          FAILED    6550       ORA-06550: 行1、列775:
                                                      PL/SQL: ORA-00942: 表またはビューが存在しません。
                                                      ORA-06550: 行1、列763:
                                                      PL/SQL: SQL Statement ignored
 

EMCC でのジョブ・チェーンの作成

ジョブ・チェーンは Enterprise Manager Cloud Control (以後 EMCC) でも作成可能です。
データベースの管理画面より、[管理]-[Oracle Scheduler]-[チェーン]の箇所より設定可能です。
実際の EMCC の画面では以下箇所からチェーンの設定を行います。

以下画面にて既存チェーンの編集や新規チェーンの作成などが実行出来ます。

上記画面の「作成」を選択すると以下のチェーンの作成画面が表示されますので以下のように任意のチェーン名やステップ、ルールなどを入力します。


引数を使用する場合

現行バージョンであるOracle Database 10.2~21cまでのバージョンでは、引数がサポートされておりません。

しかし実際に実行するジョブでは引数を含むジョブを実行させることが要件となっていることがあります。そのような場合には、引数を渡すシェルをジョブ・チェーンで実行するジョブと引数を必要とするジョブの間に作成することで対応出来ます。

【イメージ】

実際の実行例は以下のとおりです。

(1). ジョブ・チェーンに組み込むシェルを実行するプログラムを作成

 
 SQL> BEGIN
   2   DBMS_SCHEDULER.CREATE_PROGRAM(
   3   program_name   => 'TEST_PROGRAM1',
   4   program_type   => 'EXECUTABLE',
   5   program_action => '/home/oracle/work/TEST_PROGRAM1.sh',
   6   enabled => TRUE);
   7   DBMS_SCHEDULER.enable (name => 'TEST_PROGRAM1');
   8   END;
   9  /
  
 PL/SQLプロシージャが正常に完了しました。
 

(2). (1)のプログラムで実行されるシェルには引数と実行するプログラムを指定します。

 
 -- 以下シェルでは第一引数を S19000 で TEST_PROGRAM1_PLAY.sh を実行
 $ cat /home/oracle/work/TEST_PROGRAM1.sh
 /home/oracle/work/TEST_PROGRAM1_PLAY.sh S19000
 

(3). 引数が渡される処理例

 
 -- 引数で渡された値を接続先情報として別SQLファイルを実行するシェル
 $ cat /home/oracle/work/TEST_PROGRAM1_PLAY.sh
 sqlplus -l OHBA/oracle@$1 @test.sql
 
 
 -- SQLファイルの中身例
 $ cat test.sql
 -- SQL で ORA- エラーが発生した場合、ジョブを失敗させる為に
 -- WHENEVER SQLERROR EXIT FAILURE ROLLBACK を指定
 WHENEVER SQLERROR EXIT FAILURE ROLLBACK
 insert into test1 values(sysdate);
 commit;
 exit
 

まとめ

今回はデータベースの標準機能であるジョブ・チェーン機能を紹介しました。本機能はバージョン 10.2以降であれば Standard Edition 、Enterprise Edition に関わらず使用可能な機能です。外部ツールに頼らないジョブスケジュール管理も可能になるため、簡易な定期ジョブや情報収集に本機能をご利用いただくのはいかがでしょうか。


執筆者情報

おおば しょうた プロフィール画像

2020年アシストに中途入社後、Oracle Databaseサポート業務に従事。8年のOracle Databaseサポート経験を活かし、Real Application Clustersなどの高可用性製品、Enginnerd Systems を中心としたお客様対応に奮闘中。
趣味は漫画鑑賞とスノーボードで、最近はボードゲームも再熱中。

保有資格
・Oracle Master Silver
・応用情報技術者試験



■商標に関して
OracleとJavaは、Oracle Corporation 及びその子会社、関連会社の米国及びその他の国における登録商標です。
文中の社名、商品名等は各社の商標または登録商標である場合があります。

関連している記事

  • Oracle Database
  • Exadata
2021.12.23

Exadataをフル活用しよう!性能をさらに引き上げるチューニング方法(Smart Scan編)

本記事では、Oracle Exadata Database MachineにおけるSQLチューニングの手法をご紹介します。

  • Oracle Database
2021.12.22

今だから見直そうデータベースセキュリティ(後編) 

前編では、データベースセキュリティとは?を整理したうえで、データベースセキュリティ検討時に必要となる5つの観点をご紹介し、「1. データの保護」について解説しました。後編となる本記事では「2. アイデンティティとアクセスの管理」と「3. 発見的統制の実現」について解説します。

  • Oracle Database
2021.12.17

Oracle Databaseのサポート対応で依頼することの多いファイルとコマンド

お客様がOracle Databaseの運用中に問題が発生した場合、サポートセンターにお問い合わせをいただきます。調査のために依頼することの多いログファイルとコマンドをまとめましたので、情報取得の際にお役立てください。

ページの先頭へ戻る