2-Phase Commit
Claude Code.icon
登場人物
Coordinator(調整役): トランザクション全体を仕切る1ノード
Participants / Cohorts(参加者): 実際にデータを書く各ノード
2つのフェーズ
code:_
Coordinator Participants
| ── Phase 1: Prepare ──> |
| "コミットできる?" | ← 各自ローカルで準備、ログ書き込み
| <── Yes / No ─────────── |
| |
| ── Phase 2: Commit ───> |
| "じゃあコミットして" | ← 確定 or ロールバック
| <── Ack ──────────────── |
Phase 1: Prepare(投票フェーズ)
1. Coordinatorが全参加者に Prepare を送る
2. 各参加者は「コミット可能か」を判断し、可能なら必要な変更をログに永続化してロックを取り、Yes(Vote-Commit) を返す。ダメなら No(Vote-Abort)
3. 一度 Yes と答えた参加者は、もう自分では中止できない(Coordinatorの最終決定に従う義務を負う)
Phase 2: Commit / Abort(決定フェーズ)
全員が Yes → Coordinatorは Commit を決定しログに記録、全員に Commit を送る
1人でも No → Abort を送り、全員ロールバック
参加者は実行後 Ack を返し、Coordinatorが完了
なぜ2段階なのか
「いきなりコミットして」だと、ある参加者だけ成功して他が失敗したときに部分的にコミットされた不整合状態が生まれます。先に全員へ「準備=必ずコミットできる状態」を作らせ、全員のOKを確認してから確定することで、原子性(All or Nothing)を保証します。
最大の弱点:ブロッキング
2PCの致命的な問題は Coordinatorの単一障害点 です。
参加者が Yes を返した後、Phase 2の指示が来る前にCoordinatorがダウンすると、参加者は「コミットすべきか中止すべきか」を独自に決められず、ロックを握ったまま待ち続ける(in-doubt状態)
この間、対象データはロックされ続け、他のトランザクションも止まる
つまり**「安全(safety)」は満たすが「生存性(liveness)」を犠牲にする**プロトコルです。
派生・改善
Prepareとcommitの間にPre-Commitフェーズを追加し、ノンブロッキング化を狙う
ただしネットワーク分断には弱く、実用例は少ない
Coordinatorの決定自体を合意アルゴリズムで多重化し、単一障害点を解消
そもそも分散トランザクションを避け、各ローカルトランザクション+補償トランザクション(Compensating Transaction)で結果整合性を取る
マイクロサービスで主流