2相コミット(ニソウコミット)とは | 意味や読み方など丁寧でわかりやすい用語解説
2相コミット(ニソウコミット)の意味や読み方など、初心者にもわかりやすいように丁寧に解説しています。
読み方
日本語表記
二相コミット (ニーソウコミット)
英語表記
Two-phase commit (ツーフェーズコミット)
用語解説
2相コミットは、複数の独立したシステムやデータベースが関わる分散トランザクションにおいて、その処理全体が成功するか、あるいは全体が失敗するか(アトミック性と呼ばれる特性)を保証するためのプロトコルである。分散環境では、ある処理が複数のデータベースにまたがって更新を行う場合がある。例えば、銀行システムで顧客Aの口座から顧客Bの口座へ送金する処理を考える。これは顧客Aの口座残高を減らす操作と、顧客Bの口座残高を増やす操作という、通常は異なるデータベースで管理される可能性のある二つの更新処理から構成される。もし片方の処理だけが成功し、もう片方が失敗した場合、システムのデータ間に不整合が生じ、顧客Aのお金が消滅したり、顧客Bのお金が突然増えたりするなどの深刻な問題が発生する。このようなデータの整合性に関する問題を防ぎ、システム全体の信頼性を維持するために2相コミットが利用される。
2相コミットは、その名の通り「準備フェーズ」と「コミットフェーズ」という二つのフェーズに分けて処理を進める。このプロトコルには、トランザクションの全体を管理する「コーディネータ」(またはトランザクションマネージャ)と、実際にデータを操作する「参加者」(またはリソースマネージャ、例えば各データベース)という二種類の役割が存在する。
まず、第1フェーズである準備フェーズについて説明する。分散トランザクションを開始すると、コーディネータは参加者となる全てのシステムやデータベースに対し、「このトランザクションをコミットする準備ができたか」を問い合わせる。この問い合わせはPREPAREメッセージとして送信される。メッセージを受け取った各参加者は、自分自身のデータベース上で、トランザクションの全操作を完了させることが可能かどうかを判断する。もし可能であれば、参加者は必要な更新内容を一時的に保持し、その変更が永続的に行える状態であることをログに記録する(これは、後でコミットまたはロールバックできるよう、更新前の状態に戻せる情報や、更新後の状態に確定できる情報を保存することを意味する)。この状態は「準備完了」状態と呼ばれ、この時点から参加者は、コーディネータからの指示があるまで、そのトランザクションに関連するリソース(例えば更新対象のデータ行)をロックして他のトランザクションがアクセスできないようにする。準備が完了したら、参加者はコーディネータに「準備完了」の応答メッセージを送信する。もし何らかの理由でトランザクションを完了できない場合(例えば、リソース不足や整合性制約違反など)、参加者は「準備失敗」の応答をコーディネータに送信する。
次に、第2フェーズであるコミットフェーズに移る。コーディネータは、全ての参加者からの応答を待つ。ここで二つのケースに分かれる。
一つ目のケースは、全ての参加者から「準備完了」の応答を受け取った場合である。この場合、コーディネータはトランザクション全体を成功させると判断し、全ての参加者に対して「コミット」メッセージを送信する。このメッセージを受け取った参加者は、準備フェーズで一時的に保持していた更新内容を永続的に確定させ、データベースに変更を反映させる。更新が完了したら、参加者はコーディネータに「コミット完了」メッセージを送信し、トランザクションに関連するロックを解放する。全ての参加者からの「コミット完了」をもって、分散トランザクション全体が成功裏に終了したとみなされる。
二つ目のケースは、いずれかの参加者から「準備失敗」の応答を受け取った場合、あるいは一部の参加者から応答が得られない場合(例えばネットワーク障害や参加者のシステム障害によるタイムアウトなど)である。この場合、コーディネータはトランザクション全体を失敗させると判断し、全ての参加者に対して「ロールバック」メッセージを送信する。このメッセージを受け取った参加者は、準備フェーズで一時的に保持していた更新内容を破棄し、トランザクション開始前の状態にデータベースを戻す。これをロールバックと呼ぶ。ロールバックが完了したら、参加者はコーディネータに「ロールバック完了」メッセージを送信し、トランザクションに関連するロックを解放する。全ての参加者からの「ロールバック完了」をもって、分散トランザクション全体が失敗裏に終了し、システム全体のデータ整合性が保たれた状態に戻される。
2相コミットの主な利点は、分散環境におけるデータの強力なアトミック性、すなわちオール・オア・ナッシング(全て成功するか、全て失敗するか)を保証できる点にある。これにより、複数の異なるシステムにまたがる処理においても、データが途中で矛盾した状態になることを防ぎ、常に一貫性を保つことができる。
一方で、2相コミットにはいくつかの課題も存在する。第一に、性能のオーバーヘッドが大きいことである。コミットを行うまでに複数のシステム間で何度もメッセージを交換し、各参加者がログを書き込んだりリソースをロックしたりするため、単一のシステム内で行うトランザクションに比べて処理に時間がかかりやすい。第二に、可用性の問題である。特にコーディネータが準備フェーズの後に障害を起こした場合、参加者は「準備完了」状態でロックを保持したままコーディネータからの次の指示を待ち続けることになる。この状態を「インダウト状態」と呼び、参加者が保持しているロックが解放されないため、そのリソースに対する他のトランザクションもブロックされてしまう。コーディネータが復旧するまで、この問題が解決しない可能性があるため、システムの可用性に影響を与えることがある。このようなブロッキング問題は、大規模な分散システムにおいて深刻な課題となる場合がある。
これらの課題にもかかわらず、2相コミットは、銀行の勘定系システムにおける送金処理や、複数のERP(Enterprise Resource Planning)システム間でのデータ連携など、絶対的なデータ整合性が求められるミッションクリティカルな場面で、現在も広く利用されている標準的な分散トランザクションプロトコルの一つである。近年では、2相コミットの性能や可用性の課題を緩和するため、結果整合性(最終的な整合性)を許容しつつパフォーマンスを向上させるSagaパターンなど、他の分散トランザクション管理手法も登場しているが、強力なアトミック性を提供する2相コミットの重要性は依然として高い。