概要
Spring Batchではデータベースに処理結果をメタデータとして記録することができます。
このメタデータにはバッチ処理が正常に終了したかどうかが記録されているので失敗したバッチ処理の再実行に利用することができます。
この仕組みをうまく利用するためにバッチ処理でエラーが発生したときはすみやかに例外を発生して終了するようにします。
メタデータの構成
メタデータは次の6個のテーブルにより構成されています。
- BATCH_JOB_INSTANCE
バッチ処理の本体であるJobを格納するテーブル -
BATCH_JOB_EXECUTION
Jobの実行を記録するテーブル、処理が成功したか失敗したかを記録する。 -
BATCH_STEP_EXECUTION
Jobに含まれるStepの実行を記録するテーブル、処理が成功したかどうかを記録する。
Jobの一覧
メタデータからバッチ処理の状況を取得することができます。
select x.JOB_EXECUTION_ID JOB_EXECUTION_ID, x.VERSION VERSION, x.JOB_INSTANCE_ID JOB_INSTANCE_ID, x.CREATE_TIME CREATE_TIME, x.START_TIME START_TIME, x.END_TIME END_TIME, x.STATUS STATUS, x.EXIT_CODE EXIT_CODE, x.EXIT_MESSAGE EXIT_MESSAGE, x.LAST_UPDATED LAST_UPDATED, x.JOB_CONFIGURATION_LOCATION JOB_CONFIGURATION_LOCATION from BATCH_JOB_EXECUTION x inner join BATCH_JOB_INSTANCE n on x.JOB_INSTANCE_ID=n.JOB_INSTANCE_ID order by x.START_TIME, x.JOB_INSTANCE_ID, x.JOB_EXECUTION_ID
メタデータを利用した再実行
BATCH_JOB_EXECUTIONの処理結果から失敗したJobを取得して再実行を行うことができます。
Spring BatchはJobの実行終了時にプログラムを終了します。
連続してJobを実行するためにJob終了時の処理を変更します。
- CommandLineRunnerを継承したJob実行クラスより抜粋
@Override public void run(String... args) throws Exception { CommandLineJobRunner.presetSystemExiter( new SystemExiter() { public void exit(int status) { logger.trace("SystemExiter:status=" + status); } } );
メタデータから失敗したJobを取得して再実行を指示します。
再実行はCommandLineJobRunnerに渡す引数で指定します。
- 失敗したJobを取得するSQL
select x.JOB_EXECUTION_ID JOB_EXECUTION_ID, x.VERSION VERSION, x.JOB_INSTANCE_ID JOB_INSTANCE_ID, x.CREATE_TIME CREATE_TIME, x.START_TIME START_TIME, x.END_TIME END_TIME, x.STATUS STATUS, x.EXIT_CODE EXIT_CODE, x.EXIT_MESSAGE EXIT_MESSAGE, x.LAST_UPDATED LAST_UPDATED, x.JOB_CONFIGURATION_LOCATION JOB_CONFIGURATION_LOCATION from BATCH_JOB_EXECUTION x inner join BATCH_JOB_INSTANCE n on x.JOB_INSTANCE_ID=n.JOB_INSTANCE_ID where n.JOB_NAME='billingBatchJob' and x.EXIT_CODE != 'COMPLETED'
-
失敗したJobのインスタンスから成功したJobを検索するSQL
select JOB_EXECUTION_ID, VERSION, JOB_INSTANCE_ID, CREATE_TIME, START_TIME, END_TIME, STATUS, EXIT_CODE, EXIT_MESSAGE, LAST_UPDATED, JOB_CONFIGURATION_LOCATION from BATCH_JOB_EXECUTION where JOB_INSTANCE_ID = @jobInstanceId and EXIT_CODE = 'COMPLETED'
検索したJobのインスタンスに成功したJobが見つからなかったときはJobの再実行を行います。
Jobの再実行を行うときはコマンドの引数として”-restart”を指定します。
- jobExecutionIdを指定してJobの再実行
CommandLineJobRunner.main(new String[] { "com.sios.azure.billing.cost.batch.BatchConfiguration", jobExecutionId, "-restart"});
メタデータの削除
Jobの再実行を行うと条件によって必ず失敗するJobが残ってしまうことがあります。
その際にはそのJobをメタデータから削除する必要があります。
次のSQLにより特定のJobインスタンスを削除することができます。
@instance_idの記述はMySQLに合わせています。
使用しているデータベースに合わせる必要があります。
set @instance_id=1234; delete from BATCH_STEP_EXECUTION_CONTEXT where STEP_EXECUTION_ID in (select STEP_EXECUTION_ID from BATCH_STEP_EXECUTION where JOB_EXECUTION_ID in (select JOB_EXECUTION_ID from BATCH_JOB_EXECUTION where JOB_INSTANCE_ID=@instance_id)); delete from BATCH_STEP_EXECUTION where JOB_EXECUTION_ID in (select JOB_EXECUTION_ID from BATCH_JOB_EXECUTION where JOB_INSTANCE_ID=@instance_id); delete from BATCH_JOB_EXECUTION_CONTEXT where JOB_EXECUTION_ID in (select JOB_EXECUTION_ID from BATCH_JOB_EXECUTION where JOB_INSTANCE_ID=@instance_id); delete from BATCH_JOB_EXECUTION_PARAMS where JOB_EXECUTION_ID in (select JOB_EXECUTION_ID from BATCH_JOB_EXECUTION where JOB_INSTANCE_ID=@instance_id); delete from BATCH_JOB_EXECUTION where JOB_INSTANCE_ID=@instance_id; delete from BATCH_JOB_INSTANCE where JOB_INSTANCE_ID=@instance_id;