分散トランザクションのコミットプロトコル系譜
2PC からSpanner まで、分散コミットの選択肢をブロッキング性・レイテンシ・耐故障性で一気に見渡せます。なぜ現代のDBが古典2PCを捨てて合意やTrueTimeへ進んだのかが原理から腹落ちします。
- 1.古典2PC はブロッキングが宿命。コーディネータのログにしか結末が無いため、prepare 後にコーディネータが落ちると参加者がロックを抱えたまま固まる。
- 2.Paxos Commit はコミット決定そのものを合意で冗長化し、コーディネータ単一障害点を消してブロッキングを解消した。3PC は分断に弱く実務では廃れた。
- 3.Percolator はBigtable 上のクライアント駆動2PC、Spanner はPaxos 複製+TrueTime で外部一貫性を実現。系譜は「決定を1台に預けるか、合意で冗長化するか」で分岐する。
系譜を貫く一本の問い
分散コミットの全プロトコルは、たった一つの問いへの答え方で分類できます。それは「最終的な commit/abort の決定を、どこに、どう保持するか」です。2相コミット(2PC)は決定をコーディネータ1台のログに預けます。だからそのログに触れない他ノードは結末を一意に確定できず、ブロッキングが生じます。以降の進化はすべて、この「決定の所在」を冗長化・分散化していく試みとして読み解けます。
評価軸は3つに固定します。ブロッキング性(障害時にロックを抱えて固まるか)、レイテンシ(コミット確定までの往復段数)、耐故障性(何台までの故障・分断に耐えるか)です。
1981年 2PC: 決定を1台に預ける原型
2PC は prepare(投票)→ commit/abort の2フェーズ。参加者は prepare で YES を返した瞬間 in-doubt 状態となり、自分では結末を決められません。
phase1: coordinator -> all: prepare ; participant: log(YES), reply YES
phase2: coordinator: log(commit) ; coordinator -> all: commit ; reply ACK
レイテンシはコーディネータ↔参加者の2往復(prepare/投票と commit/ACK)+ログ書き込み2回(参加者の prepare ログ、コーディネータの decision ログ)。耐故障性は低く、コーディネータ障害でブロッキングします。安全性(誤った確定をしない)は常に守りますが、活性(いつ確定するか)を保証できない。これはFLP不可能性が示す非同期環境の限界と整合します。
1982年 3PC: フェーズを足して、分断で破れる
3PC は prepare と commit の間に pre-commit を挟み、「全員 YES だった」事実を全参加者へ行き渡らせます。これにより生存者はタイムアウト後に自力で前進でき、ノード故障に限ればブロッキングが消えます。
3PC が前進できるのは「落ちたノードは確かに死んでいる」という同期的故障モデルの下だけです。現実のネットワーク分断では、生きているのに通信が切れたノードを死亡と誤認します。分断の両側が別々に commit / abort へ進むと安全性そのものが破れる。往復が1段増えて遅い割に保証が脆く、本流から外れました。
2006年 Paxos Commit: 決定を合意で冗長化する
転機は「コミット決定をコーディネータ1台ではなく合意ログに書く」発想です。Gray と Lamport の Paxos Commit は、各参加者の投票を独立した Paxos インスタンスで複製し、decision も合意(Paxos/Raft)で確定します。決定がfloor(N/2)+1台に冗長化されるため、コーディネータが落ちても生存多数派が結末を再構成でき、ブロッキングが原理的に消えます。
Lamport の指摘が秀逸です。Paxos のアクセプタを1台に縮めると Paxos Commit はちょうど古典2PC に一致します。つまり 2PC は「合意の複製度が1」の特殊ケース。ブロッキングは複製度1の必然的な代償であり、複製度を上げれば消える――系譜の補助線がここで一本につながります。
2010年 Percolator: クライアント駆動2PC
Google の Percolator は Bigtable 上にスナップショット分離のトランザクションを載せた方式です。中央コーディネータを置かず、クライアント自身が2PC の調整役を務めます。各行に lock 列・write 列を持たせ、prepare 相当でロック列を立て、主ロック(primary lock)を1つ選んでそこにコミット可否を集約。主ロックの状態が真実の源になり、孤児ロックは他トランザクションが lazy に解決します。タイムスタンプは中央の Timestamp Oracle が単調発番します。
実態は2PC ですが、状態をBigtable 行に永続化することで耐障害性をストレージへ委譲した点が新しい。レイテンシはロック書き込みのぶん大きく、バッチ的なインデックス更新向けです。
2012年 Spanner: Paxos 複製+TrueTime
Spanner は前2者を統合します。各シャード(Paxos グループ)は内部を Paxos で複製し、シャード横断トランザクションをグループ間2PCで束ねます。ここが核心で、2PC の各参加者自身が Paxos で複製されたグループなので、参加者の障害がブロッキングに直結しません。決定ログもPaxosでN台に冗長化されます。
さらに TrueTime(GPS と原子時計で不確実性区間[earliest, latest]を持つ時刻API)でコミットタイムスタンプを採番し、commit-wait(不確実性区間が過ぎるまで待つ)で外部一貫性(線形化可能性)を保証します。代償は数ミリ秒のコミット待ちというレイテンシです。
系譜の分岐を表で固定する
| プロトコル | 年代 | 決定の所在 | ブロッキング | 耐故障性 |
|---|---|---|---|---|
| 2PC | 1981 | コーディネータ1台のログ | あり(in-doubt で固まる) | 低(単一障害点) |
| 3PC | 1982 | pre-commit で全参加者に共有 | 緩和(同期故障のみ) | 分断で安全性が破れる |
| Paxos Commit | 2006 | Paxos 合意ログ(多数派) | なし | 高(floor(N/2)+1 生存で前進) |
| Percolator | 2010 | Bigtable 行の primary lock | 実質なし(lazy 解決) | ストレージへ委譲 |
| Spanner | 2012 | Paxos 複製された各グループ+2PC | なし(参加者が複製済み) | 高+外部一貫性 |
分岐を箇条書きで言い切る
- 複製度1の系統: 2PC。決定が1台。速いがブロッキングが宿命。XA や
PREPARE TRANSACTIONとして現役。 - 同期故障を仮定した緩和: 3PC。分断耐性を欠き、系譜の袋小路。
- 合意で決定を冗長化する本流: Paxos Commit → Spanner。コーディネータ単一障害点を消し、ブロッキングを原理から除去。クォーラムの重なり(R+W>N の発想と同根)が安全性を支える。
- ストレージ委譲の系統: Percolator。状態を分散ストレージの行に持たせ、クライアント駆動で調整。スループット志向。
「2PC のブロッキングは決定がコーディネータのログにしか無いから。Paxos Commit はその決定を合意で複製して単一障害点を消す。2PC は Paxos Commit のアクセプタ1台版」――この3文が言えれば系譜を掌握しています。Spanner は『Paxos 複製された参加者同士の2PC+TrueTime によるcommit-wait で外部一貫性』とまとめます。
系譜を貫くのは、決定を1台に預けるか合意で冗長化するかという一軸です。古典2PC の素直さと、それが招くブロッキングという代償。現代の分散DBが Snapshot Isolation 系の並行制御と Paxos 複製を組み合わせるのは、この代償を払い終えた到達点だと理解すると、設計判断の軸が定まります。
データベース Article
分散トランザクションのコミットプロトコル系譜を実務で読む
TL;DRは入口です。実際に選ぶ・使う段階では、何を解決するか、何と比較するか、導入後にどこで詰まるかまで見る必要があります。
解決すること
分散トランザクション
比較で見る軸
難易度: advanced / カテゴリ: データベース / タグ数: 5
導入後に効く点
Paxos Commit はコミット決定そのものを合意で冗長化し、コーディネータ単一障害点を消してブロッキングを解消した。3PC は分断に弱く実務では廃れた。
先に潰すリスク
用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。
- 難易度
- advanced
- カテゴリ
- データベース
- タグ数
- 5
判断チェックリスト
- 自社の用途が「分散トランザクション / 2相コミット」に近いか確認する。
- 強みである「古典2PC はブロッキングが宿命。コーディネータのログにしか結末が無いため、prepare 後にコーディネータが落ちると参加者がロックを抱えたまま固まる。」が本当に評価軸になるか確認する。
- 注意点の「用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。」を運用で吸収できるか確認する。
- 公開値や仕様値は、対象プラン・対象機種・対象リージョンまで確認する。
- 既存システム、ID、ネットワーク、監視、バックアップとの接続方法を先に洗い出す。
- 小さく試してから、本番移行、権限設計、障害時手順、コスト監視を決める。