応用情報技術者試験の学習や、実際のシステム設計の現場で「2相コミットプロトコル(Two-Phase Commit Protocol)」という言葉を聞いたことはありますか?
特に、複数のデータベースやシステムが連携するような、少し複雑な仕組み(分散システム)を扱う際に、この言葉は非常に重要になります。
「言葉は知っているけど、正直よく分かっていない…」 「これができないと、何が困るの?」
この記事では、そんな2相コミットの基本的な考え方と、なぜそれが必要なのかを、「銀行口座間の振り込み」という身近なたとえ話で解説します。特に、システムの設計を担当する上流工程のエンジニアが、何を意識すべきかに焦点を当てていきます。
なぜ2相コミットが必要?:「銀行振込」の舞台裏
あなたは今、A銀行の自分の口座から、友人BさんのC銀行の口座へ1万円を振り込もうとしています。この処理が成功するためには、最低でも以下の2つの操作が絶対に両方とも実行される必要があります。
- A銀行のあなたの口座残高から1万円を引く。
- C銀行の友人Bさんの口座残高に1万円を足す。
もし、「1.」だけが実行されてシステムがダウンしてしまったら? あなたのお金は減ったのに、友人には届きません。
あるいは、もし「2.」だけが実行されてしまったら? あなたのお金は減っていないのに、友人の口座にはお金が増えてしまいます。
このような「中途半半端な状態」は絶対に許されません。
振り込み処理は、「両方の操作が成功する」か「両方の操作が失敗(実行前の状態に戻る)する」かのどちらかでなければなりません。
この「All or Nothing」の原則を、専門用語で原子性(Atomicity)と言います。
2相コミットの仕組み:「慎重な銀行員」の2段階確認
![[画像:2相コミットメントのサムネイル画像]](https://ssaits.jp/promapedia/wp-content/uploads/2025/10/2pc-1024x538.png)
2相コミットでは、全体の処理を監督する「調停者(Coordinator)」と、実際の処理を行う「参加者(Participant)」が登場します。
銀行振込の例では、振り込み処理システム全体が調停者、A銀行とC銀行が参加者にあたります。
処理は、その名の通り2つのフェーズ(段階)に分けて、非常に慎重に進められます。
フェーズ1:準備段階(「振り込み、本当にできますか?」の確認)
調停者から参加者に確認
調停者(振り込みシステム)は、関係する全ての参加者(A銀行とC銀行)に「コミット準備要求(Prepare)」を送ります。
「1万円の振り込み処理、実行できますか?残高はありますか?システムは正常ですか?」と確認するイメージです。
参加者の対応
各参加者(A銀行、C銀行)は、実際に処理を実行できるかを確認します。
実行可能であれば、関連するデータ(口座残高など)をロックし、「準備完了(Ready)」の応答を調停者に返します。「いつでも実行できます!」という返事です。この時点で、まだ実際の残高変更は行いません。
実行不可能(残高不足、システム障害など)であれば、「準備失敗(Abort)」の応答を返します。「すみません、実行できません」という返事です。
調停者の判断
調停者は、全ての参加者から「準備完了」の応答が返ってきた場合のみ、次のフェーズに進みます。もし一人でも「準備失敗」の応答があれば、その時点で処理全体の中止を決定します。
フェーズ2:確定段階(「全員OKなので実行!」 or 「中止します!」の指示)
ケースA:全員が「準備完了」だった場合
参加者全員が「準備完了」だった場合、調停者は、全ての参加者に「コミット要求(Commit)」を送ります。「全員準備OKなので、実際の処理を実行してください!」という最終指示です。
各参加者は、ロックしていたデータを実際に更新(口座残高を変更)し、処理が完了したら「コミット完了(Ack)」を調停者に返します。
調停者は、全ての参加者から「コミット完了」を受け取ったら、処理全体の成功を記録します。
ケースB:一人でも「準備失敗」だった場合(またはタイムアウトした場合)
もし、参加者の一人でも「準備失敗」だった場合、調停者は全ての参加者に「ロールバック要求(Rollback)」を送ります。
「問題が発生したので、今回の処理は全て中止します。もし準備のために何かロックしていたら解除してください」という指示です。
各参加者は、準備段階で行った作業(データのロックなど)を取り消し、「ロールバック完了(Ack)」を調停者に返します。
調停者は、全ての参加者から「ロールバック完了」を受け取ったら、処理全体の失敗を記録します。
この2段階の慎重な確認と指示によって、複数のシステムにまたがる処理でも「All or Nothing」(原子性)が保証されます。
上流工程で意識すべきこと
あなたがシステムの設計を担当する際、2相コミットに関して以下の点を意識する必要があります。
適用箇所の特定
システムの設計をする際、「この機能は、複数のデータベースや外部システムを同時に更新する必要があるか?」という問いかけをしてみてください。
もしYesなら、データの整合性を保つために2相コミット(またはそれに代わる仕組み)が必要になります。具体的なユースケースとしては、銀行間送金、在庫と注文の同時更新、マイクロサービス間のデータ連携などが挙げられます。
パフォーマンスへの影響
2相コミットを導入すると、原始性が保てる優れたシステムになりますが、どのようなシステムにも適しているわけではありません。
2相コミットは、全ての参加者の準備完了を待つ同期処理であり、データのロックも伴います。そのため、単一システム内のトランザクションに比べて処理時間が長くなる傾向があります。
システムの性能要件(レスポンスタイムなど)を満たせるか、十分な検討が必要です。
障害時の挙動と復旧
2相コミットを導入する際は、障害時にどのように対処するのかも、あらかじめ話し合う必要があります。
先ほどの例でいうと、もし調停者がフェーズ1とフェーズ2の間でダウンしたらどうなるでしょうか?
参加者はコミットすべきかロールバックすべきか判断できなくなります。
こうした事態を想定して、調停者の可用性をどう確保するか、障害時の復旧手順をどう設計するかが重要です。
また、参加者からの応答がない場合に、いつまで待つか(タイムアウト)、タイムアウト後にどう処理するか(一般的にはロールバック)といった、例外処理の設計が必要です。
代替手段の検討
システム要件によっては、厳密な即時整合性(2相コミットが保証するもの)が不要な場合もあります。
例えば、「数秒〜数分程度の遅延は許容できる」のであれば、結果整合性(Eventual Consistency)という考え方に基づき、Saga パターンなどのよりパフォーマンスや可用性に優れた設計を採用できる可能性があります。
このように、常に2相コミットが唯一の解ではありません。要件に合わせて最適な整合性モデルを選択することが、上流設計者の腕の見せ所です。
過去問に挑戦!
それでは、これらの知識をもとに、情報処理技術者試験の過去問を見てみましょう。
平成17年度 応用情報技術者試験 春期 午前 問69より
分散トランザクション処理で利用される2相コミットプロトコルでは,コミット処理を開始する調停者(coordinator)と,調停者からの指示を受信して必要なアクションを開始する参加者(participant)がいる。この2相コミットプロトコルに関する記述のうち,適切なものはどれか。
ア 参加者は,フェーズ1で調停者にコミット了承の応答を返してしまえば,フェーズ2のコミット要求を受信しなくても,ローカルにコミット処理が進められる。
イ 調停者に障害が発生するタイミングによっては,その回復処理が終わらない限り,参加者全員がコミットもロールバックも行えない事態が起こる。
ウ 一つの分散トランザクションに複数の調停者及び参加者が存在し得る。例えば,5個のシステム(プログラム)が関与している場合,調停者数が2,参加者の数が3となり得る。
エ フェーズ1で返答のない参加者が存在しても,調停者は強制的にそのトランザクションをコミットすることができる。
解答と解説
正解は イ です。
ア:誤り。 フェーズ1で「準備完了」を返しても、フェーズ2で調停者から「コミット要求」が来なければコミットしてはいけません。「ロールバック要求」が来る可能性もあるからです。
イ:正しい。 これが2相コミットの弱点の一つです。調停者がフェーズ1とフェーズ2の間でダウンし、復旧できなくなると、参加者は最終的な指示(コミットかロールバックか)を受け取れず、中途半端な状態で待ち続ける(ブロッキングされる)可能性があります。
ウ:誤り。 1つの分散トランザクションにおける調停者は必ず1人です。複数の調停者がいると、指示が矛盾する可能性があります。参加者は複数存在します。
エ:誤り。 フェーズ1で全ての参加者から「準備完了」の応答がなければ、調停者はコミットできません。応答のない参加者がいる場合や、一人でも「準備失敗」の応答があれば、ロールバックしなければなりません。
令和6年度 応用情報技術者試験 春期 午前 問27より
2相コミットで分散トランザクションの原子性を保証する場合,ネットワーク障害の発生によって参加者のトランザクションが,コミットすべきか又はロールバックすべきかを判断できなくなることがある。このような状況を発生させるネットワーク障害に関する説明として,適切なものはどれか。
ア 調停者のトランザクションが,コミット又はロールバック可否の問合せを参加者に送る直前に障害になった。
イ 調停者のトランザクションが,コミット又はロールバックの決定を参加者に送る直前に障害になった。
ウ 調停者のトランザクションに,コミット又はロールバック可否の応答を参加者が返す直前に障害になった。
エ 調停者のトランザクションに,コミット又はロールバックの完了を参加者が返す直前に障害になった。
解答と解説
正解は イ です。
この問題は、2相コミットプロトコルのどのタイミングで障害が発生すると、参加者が最も困る(判断不能になる)かを問うています。
先ほどの「銀行振込」のたとえで考えてみましょう。
フェーズ1: 調停者(振り込みシステム)が参加者(A銀行、C銀行)に「準備OK?」と確認し、参加者は「OK(準備完了)」または「NG(準備失敗)」を返します。
フェーズ2: 調停者は全員から「OK」が来た場合のみ「実行(コミット)!」、一人でも「NG」なら「中止(ロールバック)!」の最終指示を出します。
参加者が「コミットすべきか、ロールバックすべきか判断できなくなる」のは、フェーズ1で「OK(準備完了)」と返事をした後、調停者からの最終指示(フェーズ2のコミット要求またはロールバック要求)が届かない場合です。自分は準備万端ですが、全体としてGOなのかSTOPなのか分からない、という宙ぶらりんの状態ですね。
それでは、各選択肢を見ていきましょう。
ア:誤り。 フェーズ1の「準備OK?」の問い合わせが来る前に調停者がダウンした場合。参加者はまだ何も依頼されていないので、判断に迷うことはありません。
イ:正しい。 フェーズ1で参加者全員から「OK」の返事をもらい、調停者が「よし、コミットだ!」と決定した後、その最終指示を参加者に送る直前に調停者がダウン(またはネットワーク障害)した場合。参加者は「OK」と返事して待っているのに、最終指示が来ないので、コミットして良いのか、それとも(他の参加者がNGだったなどで)ロールバックになるのか、判断不能になります。
ウ:誤り。 参加者がフェーズ1の「OK/NG」の応答を返す直前に障害が発生した場合。調停者はその参加者からの応答を受け取れないため、タイムアウトなどで最終的に「ロールバック」を決定します。他の正常な参加者はロールバック指示を受け取ることになります。
エ:誤り。 参加者がフェーズ2の最終指示(コミットまたはロールバック)を受け取り、処理を完了して「完了しました」と報告する直前に障害が発生した場合。参加者はすでに最終的な指示を知っているので、判断不能にはなりません。
このように、参加者が最も困るのは、フェーズ1でコミットの準備を完了したものの、フェーズ2の最終決定(コミットかロールバックか)の指示を調停者から受け取れなくなったタイミングです。
まとめ
- 2相コミットプロトコルは、複数のシステムにまたがる処理の原子性(All or Nothing)を保証する仕組み。
- 「銀行振込」のように、中途半端な状態が許されない処理に不可欠。
- フェーズ1(準備確認)とフェーズ2(確定指示)の2段階で慎重に処理を進める。
- 上流工程では、適用箇所の特定、パフォーマンスへの影響、障害時の挙動、代替手段(結果整合性など)を考慮した設計が重要。
2相コミットは、分散システムの信頼性を支える重要な技術です。その仕組みとトレードオフを理解し、システム要件に合った適切な設計を行いましょう。