2PCのメリット|分散更新をそろえる仕組みと導入前に知るべき落とし穴

2PCのメリット|分散更新をそろえる仕組みと導入前に知るべき落とし穴

こんにちは、ゲーミングPC完全ナビ2.0のヨシハルです。

「2PCを使えば、複数のデータベースの更新を必ずそろえられる?」「Sagaとの違いは?」と迷っていませんか。注文と在庫のように、片方だけ更新されると困る処理では、方式の選択が大切です。

この記事では、2PCのメリットを二相コミットの仕組みから説明し、準備後の障害で起こる待ち時間や、Sagaとの使い分けまで整理します。まず押さえたいのは、2PCが役立つのは参加するシステムが分散トランザクションに対応し、障害から最終決定まで復旧できる構成を用意できる場合だという点です。

  • 2PCの準備フェーズと確定フェーズの流れ
  • 分散更新をまとめて確定できるメリット
  • 準備後の障害、ロック保持、運用上の注意点
  • Sagaとの違いと採用前に確認する条件

2PCのメリットを理解するための仕組み

2PCの準備と確定の流れ

2PCは「全員が準備できたかを確かめてから、全体の結論を出す」方式です。この順序がわかると、メリットと弱点の両方が見えてきます。

2PC(二相コミット)とは

2PCはTwo-Phase Commit(二相コミット)の略です。複数のデータベースなど、分散トランザクションに参加できる資源の更新について、全体としてコミットするか中止するかを決めるための仕組みです。

たとえば、注文データベースに注文を登録し、別の在庫データベースで在庫を減らす処理を考えてみましょう。両方を一組として確定できれば、「注文だけ入った」「在庫だけ減った」という結果を避けやすくなります。ただし、この例が2PCで成り立つのは、両方のデータベースと調整役が必要な機能に対応している場合です。

決済APIやメール送信などの外部処理は、呼び出しただけで2PCの参加者になるわけではありません。取り消しにくい外部処理を含む場合は、別のワークフローや補償処理も検討してください。

準備と確定の2段階で進む

2PCにはコーディネーターという調整役と、更新を担当する参加者がいます。全体の進行は次の2段階です。

  1. 準備フェーズ:コーディネーターが各参加者に確定可能かを問い合わせます。参加者は更新を準備し、確定できる状態なら賛成、できなければ反対を返します。この時点では全体のコミットはまだ決まっていません。
  2. 確定フェーズ:全員が賛成すればコーディネーターがコミットを決定し、参加者に伝えます。誰かが準備できなければ中止を決定します。参加者は通知された決定に従い、コミットまたはロールバックします。

PostgreSQLにも、準備、準備済みトランザクションのコミットとロールバックに対応する機能があります。ただし公式資料は、これらを外部のトランザクション管理システムと組み合わせて使うことを想定しています。(出典:PostgreSQL公式ドキュメント「PREPARE TRANSACTION」)

大切なのは決定の境目です。中止と決まった処理は取り消しますが、コミットが決定された後に通知が途切れた場合は、復旧してその決定を完了させます。「通信が失敗したら常に全体を戻す」とは考えません。

最大のメリットは分散更新の原子性

2PCの中心的なメリットは、対応する複数の参加者について、一つの全体的なコミット判断を共有できることです。原子性とは、対象の更新を「ひとまとまり」として扱う性質を指します。

参加者ごとに個別に確定すると、先に確定したデータベースだけが更新され、後の更新が失敗する可能性があります。2PCでは全員の準備を確かめてから全体の決定を出すため、そのような部分的な確定を防ぐ設計ができます。

ただし、参加者への通知が同じ瞬間に届くわけではありません。障害中は確定待ちの参加者が残ることもあります。「全員が即座に同じ状態に見える」保証ではなく、復旧を含めて同じ最終決定に従わせる仕組みとして理解すると正確です。

アプリ側の取り消し処理を減らせる場合がある

対応するデータベースの更新を2PCにまとめられれば、先に確定した処理を打ち消すための個別の業務ロジックを減らせる場合があります。更新が多い処理では、どの参加者が確定したかをアプリ側で細かく追いかける負担も抑えられます。

一方、送金通知や外部決済のように2PCへ参加できない処理まで自動で取り消せるわけではありません。メリットが及ぶ範囲は、実際に同じ分散トランザクションへ参加できる資源に限られます。

ACIDのうち何を担うのか

ACIDは原子性、一貫性、分離性、永続性を表す言葉です。2PCが主に扱うのは、複数の参加者にまたがるコミット判断の原子性です。

業務上の一貫性を保つルール、同時更新をどう分離するか、記録を障害後まで残す仕組みは、参加するデータベースやアプリケーション、トランザクション管理システムの設計にも依存します。2PCを使うだけでACIDのすべてが自動的に完成するわけではありません。

◆ヨシハルのワンポイントアドバイス

まず「どこからどこまでを同時に確定したいか」を図にしてみてください。参加できない外部サービスが混ざっていないか、早い段階で見つけやすくなりますよ。

2PCのメリットを生かす条件とSagaとの違い

2PCのメリット、弱点、Sagaとの比較

仕組みが合っていても、待ち時間や障害復旧の負担が要件に合わなければ採用しにくいものです。実際の設計では、利点と引き換えになる条件を一緒に確認しましょう。

2PCのメリットを整理

観点 得られること 成立する条件
原子性 対象の更新を一つの決定に従わせられる 全参加者が2PCに対応する
部分的な確定の防止 準備できない参加者がいれば確定前に中止できる コーディネーターが全体を調整する
取り消し設計 対象資源間の個別補償を減らせる場合がある 外部処理を対象に混同しない
運用上の追跡 トランザクション単位で準備と決定を追える 決定の記録と復旧手順を整える

特に価値があるのは、複数の対応データベースを更新し、どちらか片方だけの確定を業務上許せない場面です。一方で、単一データベース内で完結できるなら、まず通常のローカルトランザクションで足りないか確認するのが自然です。

準備後の障害では待ちが起きる

2PCの代表的な弱点はブロッキングです。参加者が「確定できます」と答えて準備状態になった後、コーディネーターから最終決定が届かないと、参加者は安全に独断で確定や中止をしにくくなります。

準備済みの状態が長引くと、保持しているロックなどがほかの処理に影響する場合があります。単にタイムアウトを短く設定すれば解決する話でもありません。最終決定がすでに出たかを確認せずに取り消すと、全体の判断と食い違うおそれがあるためです。

障害が起きた時点で必ず全体をロールバックできるわけではありません。準備前の失敗、準備後の決定待ち、コミット決定後の通知失敗を分けて考え、記録された決定に沿って復旧させる必要があります。

通信と運用のコストも見積もる

2PCでは準備の問い合わせと確定・中止の通知が必要です。参加者やネットワークの状態に処理時間が左右され、準備状態で待つ時間が延びるとロック競合も起こり得ます。

採用するなら、調整役の障害復旧、決定の永続的な記録、長く残る準備済みトランザクションの監視、復旧を担当する運用手順まで含めて設計したいところです。性能については、想定する同時実行数と障害条件で実測して判断しましょう。

2PCが向くケース

たとえば、複数のトランザクション対応データベースをまたぐ更新を一組として扱い、一時的な確定待ちより部分的な確定を避けることを優先する場合は、2PCが候補になります。注文記録と在庫引当を別々の対応データベースで管理する設計などが検討例です。

「会計だから2PC」「決済だから2PC」と業種名だけで決めるのは避けましょう。単一DBで完結する処理、2PC非対応の外部APIを含む処理、長い間ユーザー操作を待つ処理では、別の構成が適することがあります。

Sagaとの違いは「いつ確定するか」

Sagaは、一連の処理を各サービスのローカルトランザクションとして順に確定する方式です。途中で失敗した場合は、それまでに確定した処理に対して補償トランザクションを実行し、業務上つじつまの合う状態へ進めます。Microsoftの設計資料でも、各段階の確定、補償、再試行や監視が説明されています。(出典:Microsoft Learn「Saga 分散トランザクション パターン」)

2PCは準備後に全体のコミット判断を出します。Sagaは各段階がすでに確定しているので、失敗時の補償はデータベースのロールバックと同じではありません。補償が失敗したり、元の状態へ完全には戻せなかったりする場合もあります。その代わり、各サービスに長時間の分散トランザクションへの参加を求めずに済む構成を選べます。

比較項目 2PC Saga
確定の仕方 全参加者の準備後に全体の判断を出す 各段階をローカルで順に確定する
失敗したとき 決定前なら中止。決定後は記録に従い復旧する 確定済みの段階を必要に応じて補償する
必要な設計 対応資源、調整役、決定の記録、障害復旧 補償、再試行、べき等性、進行状況の監視
主な注意点 準備後の待ちとロック保持 途中状態の可視性と補償失敗

Sagaを選んでも「必ず止まらない」わけではありません。外部サービスの障害や補償の失敗は残ります。許容できる途中状態と、失敗時に回復できる業務手順を具体的に決めることが重要です。

採用前に確認したい5つのこと

  • 対象範囲:一緒に確定したい更新は、すべて2PCに参加できるか
  • 代替手段:単一DBのトランザクションで処理をまとめられないか
  • 待ち時間:準備済みの参加者が障害復旧を待つことを許容できるか
  • 復旧運用:決定の記録、未完了の検知、再開手順を用意できるか
  • 外部処理:決済APIや通知など、2PCの外にある処理をどう扱うか

これらを確認すると、「原子性が大事だから2PC」と短絡せず、実際の構成に合う方式を選びやすくなります。

◆ヨシハルのワンポイントアドバイス

障害試験では、準備直後とコミット決定直後に調整役が止まった場合を分けて確認しましょう。どの記録を見て誰が復旧するのかまで決めると、採用後の困りごとを減らせます。

2PCのメリットに関するよくある質問

Q1. 2PCのいちばん大きなメリットは何ですか?

A. 2PCに対応する複数の参加者が、同じ全体的なコミット判断に従えることです。片方だけ先に確定する設計を避け、分散更新の原子性を実現しやすくなります。

Q2. 2PCなら障害時に必ず全体を戻せますか?

A. いいえ。全体のコミットが決定される前なら中止できますが、決定後の通知失敗は記録された決定に従ってコミットを完了させます。準備後に決定がわからなくなった参加者は、復旧まで待つことがあります。

Q3. 2PCの主なデメリットは何ですか?

A. 準備後に最終決定を待つ間、処理やロックが残り得ることです。通信や調整のコスト、未完了の準備済みトランザクションを監視・復旧する運用負担もあります。

Q4. Sagaとの違いは何ですか?

A. 2PCは全参加者の準備後に全体の確定を決めます。Sagaは各段階を順に確定し、後の段階が失敗したら補償処理で調整します。補償は必ず成功するわけではないため、再試行と監視も必要です。

Q5. 決済や在庫管理なら2PCを選ぶべきですか?

A. 業務名だけでは決まりません。対象の資源が2PCに参加できるか、単一DBで完結できないか、待ち時間と障害復旧を許容できるかを先に確認します。外部の決済APIは2PCに参加できない場合もあります。

2PCのメリットと採用判断のまとめ

2PCのメリットは、対応する複数の資源の更新について、全体で一つのコミット判断を共有できることです。準備がそろう前の部分的な確定を避けたい場合に役立ちます。

一方で、準備後に決定を待つ間はロックや処理が残り得ます。2PCを採用するなら、参加資源の対応、調整役の復旧、決定の記録、待ち時間を合わせて設計してください。外部処理を含む長い業務フローなら、Sagaと補償処理の検討も必要です。

まずは更新対象を書き出し、一組として確定すべき範囲と、障害時に待てる時間を確認してみてください。それが2PCを使うべきか判断する出発点になります。