Part1とPart2では,ACID特性を満足する「ACIDトランザクション」について,説明してきました。しかし,「疎結合」のWebサービスで非同期のメッセージ交換を行うような取引は,ACIDトランザクションとして扱えない場合があります。そうした場合は,「ロングラニングトランザクション」の概念が有効になります。

 ここまでは,ACID特性を満足する「ACIDトランザクション」について,説明してきました。ACIDトランザクションは,銀行のATM(現金自動預け払い機)のような,クライアントからの要求をサーバーが処理して応答を返すサービス処理時間が短いリアルタイム処理に適用できます(「Short-Lived Transaction」と言うこともあります)。

 しかし,企業取引の中には,システム間連携,企業間連携など他のシステムとの統合が必要になる場合があります。このような連携処理は,一般的に「疎結合」で構成され,Webサービスなどを使用してメッセージ交換を行います。それぞれのWebサービスはお互いにデータを共有することもなく,動作する場所も管理方法も異なるのが一般的です。また,このような環境では,1つの取引の中に長時間(数十分や数時間,数日間)かかる業務サービスが含まれていることがあります。

 こうした長時間かかる業務サービスと連携する取引に,これまで説明してきたACIDトランザクションを適用できるでしょうか?

 例えば,トランザクション境界に複数のWebサービスが含まれ,そのサービスが長時間に及ぶ状況を考えてみましょう。たとえ2フェーズコミットを実装できたとしても,それぞれのリソースのロック時間が長くなり実用的ではありません。Webサービスを連携するような場合には,これまで説明してきたACIDトランザクションとは特性が異なる,もっと柔軟なトランザクションの仕組みが必要になります。

 このような長時間の処理を含むトランザクションを,「ロングラニングトランザクション(Long running transaction)」あるいは「Long-Lived Transaction」と呼びます。例えば,ある業務の流れの中で,クライアントがサービスAとサービスBに要求を送り,その結果を受信する処理を考えてみましょう(図1)。条件は,

(1)サービスAとサービスBがともに成功した場合のみ成功を返します。

(2)サービスAとサービスBのどちらかが失敗した場合は,成功したサービスをロールバックし,エラーを返します。

(3)サービスAとサービスBの処理はそれぞれ平均数時間かかると想定します。

図1●ロングラニングトランザクションの実行例
図1●ロングラニングトランザクションの実行例
[画像のクリックで拡大表示]

 このようなアプリケーションを実装するためには,1つのACIDトランザクションではなく,次のように複数のACIDトランザクションに分離して実装します。

トランザクション1

クライアントAがトランザクションを開始後,サービスAとサービスBの要求をキューに書き込み,コミットします。キューに書き込んだ時点で,別のアプリケーションがリソース(キュー)を利用可能になります(長時間ロックされません)。

トランザクション2

クライアントBがトランザクションを開始して,キューからサービスA要求を読み込み,サービスAを実行してコミット。その結果をクライアントAに通知します。

トランザクション3

クライアントCがトランザクションを開始して,キューからサービスB要求を読み込み,サービスBを実行しコミット。その結果をクライアントAに通知します。

 トランザクション2およびトランザクション3においてキューからサービス要求を取り出した後にサービス要求が失敗した場合はキューに戻されます。トランザクション2およびトランザクション3のACID特性から,サービス要求が「消失」することはありません。

 クライアントAは,クライアントBとクライアントCからの応答(コールバックまたはポーリングにより入手)により,必要に応じて補償トランザクションを実行します。

 この処理の流れは,2フェーズコミットと異なり,準備フェーズがありません。このため,トランザクション2またはトランザクション3が異常終了した場合に,不整合な状態になります。この場合,アプリケーションレベルでフォワードリカバリー(処理を前に進めるリカバリー)またはロールバックリカバリー(処理を後ろに戻すリカバリー)を行います(補償トランザクション)。

 例えばトランザクション3が異常終了した場合,トランザクション2は,補償トランザクションが終了するまで不整合なデータを保持し,他のアプリケーションからアクセスされる可能性があります。この間,トランザクションの「隔離性」は保証されていません)。つまり,補償トランザクションが完了するまでは,ACID特性の一部が失われているのです。

 Webサービスの標準規格の中でもロングラニングトランザクションの取り扱いについて仕様が決まっています。ロングラニングトランザクションに含まれる一部の処理が異常終了した場合は,ロングラニングトランザクションを制御する「トランザクションコーディネータ」が,ロングラニングトランザクションの整合性を取るためにアプリケーションレベルのリカバリー・プログラムを実行するよう指示します(補償トランザクション)。

 ロングラニングトランザクションは,ACID特性の中の「隔離性」を緩やかに規定することで,アプリケーションの並行処理を高めながら,トランザクション終了時に「原子性」,「一貫性」,「持続性」を保証するトランザクションと言うことができます。開発者は,ロングラニングトランザクションを使用する場合に,緩い「隔離性」が業務的に問題が無いことや,例外処理としてリカバリロジックを作成することが必要です。

 このようなロングラニングトランザクションを設計,実装するために,Webサービスのトランザクション関連の規格やBPM(Business Process Management),BPEL(Business Process Execution Language for Web Services)を使用することができます。これらに対応した製品を利用すれば,開発者はワークフローでWebサービスを順次呼び出したり,トランザクション境界を設定したり,例外が発生した場合の補償トランザクションロジックを設定することができます。各製品のエンジンがこれらのワークフローを自動的に実行してくれるので,開発者はビジネスロジックの開発に専念することができます

トランザクション境界,例外処理,トランザクションタイムアウトがカギ

 本講座では,初歩の初歩からトランザクションの概要を説明しました。これまで何となくトランザクション処理は面倒,複雑だ,と敬遠していた開発者の方々も,トランザクションマネージャを活用することにより,信頼性が高く,優れた性能の堅牢なアプリケーションをシンプルに実装できることが,お分かりいただけたのではないでしょうか。

 アプリケーション開発者にとって特に重要な点は,トランザクション境界の設定,例外処理,トランザクションタイムアウトです。トランザクション境界は,トランザクションマネージャの内部の動作をイメージしながら,無駄のない設定を行なう必要があります。また,適切に例外を処理するロジックも必要になります。さらにアプリケーションロジック,リソースマネージャ側の処理時間を含めた最適なトランザクションタイムアウト値の設定により,障害が発生しても迅速にリカバリーすることが可能になります。

 特にSOA(サービス指向アーキテクチャ)に基づいたシステム設計を行う場合に,ACIDトランザクションとロングラニングトランザクションを適材適所で使い分けることは非常に重要になるでしょう。

 ミッションクリティカルシステムでは,分散トランザクションの「死角」である「インダウトトランザクション」を解決する際に起こり得る「ヒューリスティック決定」時の不整合を解決するときやロングラニングトランザクションで発生する可能性のある「補償トランザクション」を考慮したリカバリー処理も必須です。本講座で述べた分散トランザクションの基礎技術が,アプリケーション開発のための一助になれば幸いです。