企業のアプリケーションでは,どんな傷害が起こってもトランザクションのACID特性が保証される仕組みが必要になります。では,2フェーズコミットを実装している分散トランザクション環境において,障害発生時にトランザクションのACIDはどのように保障されるのでしょうか?Part2では,DTPモデルに準拠した一般的な分散トランザクション処理における,トランザクションのリカバリーについて説明しましょう。

 企業のアプリケーションでは,あらゆる障害に対して,データの保全と整合性を保証する仕組みが必要です。トランザクション処理中に,サーバーやネットワーク,データベース,またはトランザクションマネージャに障害が発生した場合に,データを失ったり,不整合な状態になったりすることは,絶対に避けなければなりません。つまり,トランザクションのACID特性を保証することが必須になります。

 では,2フェーズコミットを実装している分散トランザクション環境において,トランザクションのACIDは,どのように保証されるのでしょうか?ここでは,DTPモデルに準拠した一般的な分散トランザクション処理における,トランザクションのリカバリーについて説明しましょう。

 まず準備フェーズ障害が発生した場合を考えましょう。あるリソースマネージャに障害が起こったとき(つまり,xa_prepareの応答としてxa_okが返ってこなかったとき)は,トランザクションマネージャがすべてのリソースマネージャにxa_rollback要求を発行して,リソースマネージャを元の状態に戻すことで,グローバルトランザクションをロールバックします。準備フェーズでトランザクションマネージャに障害が起こったときは,リソースマネージャ自身がタイムアウトにより仕掛かり中のトランザクションをロールバックすることで,グローバルトランザクションはロールバックされます。

 では,コミットフェーズでリソースマネージャやトランザクションマネージャに障害が起こったときは,どうなるのでしょうか。

 コミットフェーズで,あるリソースマネージャに障害が発生した場合は,次のような流れになります(図1)。

図1●コミットフェーズでリソースマネージャBに障害が発生した場合のリカバリー
図1●コミットフェーズでリソースマネージャBに障害が発生した場合のリカバリー
[画像のクリックで拡大表示]

(1)トランザクションマネージャは,障害が起こったリソースマネージャに対してxa_commit要求のリトライを続けて行ないます。

(2)トランザクションタイムアウト(後述)になった場合,コミットを諦めて,そのリソースマネージャにxa_rollback要求を発行します。

(3)ロールバックを指示されたリソースマネージャはロックを開放します(グローバルトランザクションは破棄される)。

(4)その結果,既にコミットしたリソースマネージャとロールバックしたリソースマネージャ間でデータが不整合になります。

(5)データの不整合を解消するために,管理者がグローバルトランザクションをコミットするのかロールバックするのかを判断した上で,リカバリー・プログラムを実行することによって,すべてのリソースマネージャをコミット,またはロールバックします。

 上の(5)のように,グローバルトランザクションのリカバリーを,トランザクションマネージャのレベルではなく,アプリケーションのレベルで実行することを「補償トランザクション(または補正トランザクション)」と呼びます。

 では,コミットフェーズでトランザクションマネージャに障害が発生した場合は,どうなるでしょう。

 リソースマネージャは,xa_prepare要求に対してxa_okを送信した後,xa_commit要求が送られてくるのを待ちます。その間,リソースマネージャのデータはロックされた状態です。トランザクションマネージャからxa_commit要求が届かなければ,リソースマネージャはロックされたままになります。このようなトランザクションは,リソースを圧迫したり,他のトランザクションを妨げたりする可能性があります。この不確定な状態のトランザクションを「インダウトトランザクション」と呼びます。この状態は一刻も早く解消しなくてはいけません(図2)。

図2●コミットフェーズでトランザクションマネージャに障害が発生した場合のリカバリー
図2●コミットフェーズでトランザクションマネージャに障害が発生した場合のリカバリー
[画像のクリックで拡大表示]