バッチ処理のデータストア
バッチ処理では大量データを扱うことが多いため、まずはそのデータを扱うデータストアを確認する必要があります。バッチ処理の入力データはファイルなのかRDBなのか、バッチ処理した結果をファイル出力するのかRDBに出力するのか等です。このように目的や用途に応じてファイルシステムに保存するのかRDBに保存するのかを検討します。また、ファイルの場合はTSVなのかCSVなのかXMLなのか等のファイル形式も検討します。
ジョブと順序制御
業務的に意味のある1つのバッチ処理を、ジョブと言います。通常、バッチ処理は多くのジョブで構成されているため、以下を検討する必要があります。
- 何をジョブとするのか
- 各ジョブの実行順序は問題ないか(その実行順序でデータの不整合は発生しないか)
- エンハンス開発等の場合、既存ジョブと実行順序は問題ないか
- オンライン処理とのデータの排他制御(これに関しては、排他制御(楽観ロック・悲観ロック)の基礎でも軽く触れています)
トランザクション管理
RDBを利用したバッチの場合、以下の観点でトランザクション管理を設計する必要があります。
- スループットやシステムリソースへの影響
- データ不整合の回避
1. スループットやシステムリソースへの影響
冒頭でも書きましたが、バッチ処理は大量データを扱うことが多いです。それらの大量データに対して一度にコミットすることもできれば、1件ごとのコミットをすることも可能です。大量データに対して一度にコミットする方がスループットが高くなる可能性がありますが、その分RDBの更新ロックを長時間確保することになります。更新ロックの長時間確保は、RDBの特定リソース(ロールバック用領域)を大量に消費する可能性があるため注意が必要です。また、データ量が多いとその分ロールバックに時間がかかったり、データ更新の進捗状況も把握できないため処理時間があまりにも長いと、システム障害(RDBのハングアップ等)と見なしてバッチを強制終了させるかどうかの判断も難しくなります。
2. データ不整合の回避
バッチを並列実行させる場合、ジョブ同士が同じデータを更新するケースを考慮する必要があります。
リラン時の制御
バッチ処理中に何らかの障害が起因でアベンドしたりアボートさせたりで処理が中断した場合、そのバッチを再度実行し未処理のデータ更新を続行させる必要があります。こういったケースでバッチを再実行することをリランと呼びます。リランするケースを考慮し、同じバッチを2回以上実行しても更新済みのデータはスキップする等、同じデータの二重更新を避ける等の制御が必要です。よく見かけるのは、更新済フラグ等を設けて制御をする、といった方式です。
入力データの検証とエラーハンドリング
バッチ処理の入力データがオンライン処理によるものであれば、オンライン処理の検証ロジックで信頼性が担保されているため、あえてバッチ処理で検証ロジックを入れる必要はないと思います。ただ、入力データが他システムから受領したファイルやユーザーがアップロードしたファイル等の場合、信頼性が不十分なためバッチ処理で検証ロジックを搭載する必要があります。
検証の結果エラーとなった場合、それらをハンドリングする必要がありますが、それにはいくつか選択肢があります。
- 1件でもエラーが発生すればバッチ処理全体を中断させる
- エラーが発生したら当該データをスキップさせバッチ処理を継続させる
- エラーの件数に許容値を設けてそれを超過したらバッチ処理を中断させる
1. 1件でもエラーが発生すればバッチ処理全体を中断させる
この方式は、全てのデータの入力値が妥当でなければバッチ処理を最後まで続行させることはできません。どの単位でデータコミットするかによりますが、最後にまとめてコミットする方式を採用する場合、最後のデータ更新時の入力チェックでエラーが発生した場合、それまで成功していた全ての更新をロールバックし再度やり直し、、といった具合に効率的にはあまりよくありません。
2. エラーが発生したら当該データをスキップさせバッチ処理を継続させる
この方式で重要なのは、エラーが発生したため更新をスキップした旨をログ等に残しておき、後から運用でリカバリ可能な状態にしておくことです。
3. エラーの件数に許容値を設けてそれを超過したらバッチ処理を中断させる
1と2の中間的な考え方で、エラーの件数に許容値を設けそれを超過したらバッチを終了させます。2の方式の場合、スキップデータが多すぎると運用でのリカバリに時間がかかることも想定されるため、リカバリ可能な件数を予め運用担当者と合意をしておき、それを許容値として定義しそれを超過したらバッチを中断させます。
以上です。