Live By The Code

元業務系プログラマの呟き

jbatchのジョブ管理用DBについて

ジョブ管理用DBとは

jbatchでは、実行したジョブについて以下のような情報が履歴として残るようになっている。

  • ジョブプロパティ
  • ジョブの開始時刻、終了時刻、終了ステータス
  • 各ステップの処理件数、開始時刻、終了時刻、終了ステータス

履歴として随時参照できる他、このような情報を保持することで、異常終了したジョブの再実行の際、正常に終了したステップやチャンクについては処理をスキップし、まだ処理が終わっていないチャンクから処理を再開する、といった事が出来るようになっていたりする。

履歴の確認方法

Webの管理コンソールから確認する方法の他に、CLIのasadminコマンドから確認することもできる。後者の方が軽いので、慣れてきたら基本的には後者を用いるのが良いだろう。

  • 管理コンソールを開き、左サイドバーの「サーバー(管理サーバー)」を選択後「バッチ」タブを選択
  • asadminのlist-batch-jobs, list-batch-job-steps, list-batch-job-executionsコマンドを使う

ジョブ管理用DB用データソースの確認/変更方法

GlassFish4付属の実装の場合、デフォルトでは埋め込みDerbyに保持するようになっている。データソース名は以下コマンドで確認できる。

$ ./asadmin list-batch-runtime-configuration
DATASOURCELOOKUPNAME  EXECUTORSERVICELOOKUPNAME                   
jdbc/__TimerPool      concurrent/__defaultManagedExecutorService  
Command list-batch-runtime-configuration executed successfully.
$ 

変更する場合は以下コマンド(データソースjdbc/__defaultに変更する例)。

./asadmin set-batch-runtime-configuration --datasourcelookupname jdbc/__default

またWebの管理コンソールからも確認および変更が可能。左サイドバーの「サーバー(管理サーバー)」を選択後「バッチ」タブを選択、さらに「構成」タブを選択すると変更画面が現れる。

ジョブ管理用DBを変更する場合における注意点など

JDBC接続プール定義

JDBC接続プールを定義する際「リソース・タイプ」は「javax.sql.XADataSource」を選択する。

「javax.sql.DataSource」を選んでしまうと、ジョブ実行時に以下のような例外が発生して正常に動作しない。

SQLException: 接続の割当でエラーが発生しました。
原因: java.lang.IllegalStateException: ローカル・トランザクションには、すでに1つの非XAリソースがあります: これ以上リソースを追加できません。

必要なテーブル等の準備

Derbyの場合は必要なテーブル等が存在していなければ自動的にDDLを流してくれるようになっているが、他のDBの場合はDDLを手動で流してやる必要がある。/glassfish-4.0/glassfish/lib/install/databases に各種RDB用のものが存在するのでそれを使えば良いようだ。ただし…

Derby以外はテストされていない?

前述のDDLを使いPostgreSQLに変更する事を試みたが、テーブルを作った後いざジョブを実行すると、フレームワーク側で実行するSQL文の構文エラーとなり正常に動作しなかった。他のDBでは検証していないが、今のところDerby以外での動作は確認できていない。

意外に負荷が高い

step要素内でchunk要素を使っている場合、コミットの度にblobのUPDATEが走るため意外に負荷が高い(おそらくcheckpointを記録していると思われる)。

ジョブ履歴を確認するためにはasadminコマンドか管理コンソールを使うが、これが履歴の件数に比例してどんどん重くなるため、Derbyをサーバモードにして直接テーブルを覗けないかと考えたのだが、前述の通りの重いクエリが頻繁に走るため、埋め込みモードに比べてパフォーマンス劣化がかなり大きくなってしまう。

手元のあるバッチでは起動から終了までに3倍の時間がかかるようになってしまい堪え難いので、個人的には、落としどころとして、埋め込みDerbyをジョブ管理用DBとして使い履歴がある程度溜まったら定期的にテーブルを掃除する運用にしている。

この際、GlassFish4のデフォルトではEJBタイマ用データソースと同じデータソースに設定されているので、これを別途新しく定義したバッチ管理用データソースに変更しておき、埋め込みDerbyのディレクトリごと退避してしまう運用にすれば手間がかからない。

undeployすると履歴は消去される?

基本的にはアプリケーションをundeployすると履歴は全て消去されるようになっているが、消去されない場合もあるようだ。どのような条件で消去されるのか、されないのかは不明である。