Two-Phase Commit Protocol (2PC): Distributed Transactions, Failure Recovery, and Saga Patterns

The Two-Phase Commit (2PC) protocol is an atomic commitment protocol designed to guarantee strict ACID transaction semantics across distributed database nodes. When a transaction spans multiple independent database shards, message brokers, or microservices, 2PC ensures that all participating nodes either atomically commit the mutation or collectively roll back to their previous consistent states.

This article details the protocol state machines, failure recovery mechanics, blocking limitations, and modern alternatives (3PC, Paxos-backed commit, and the Saga Pattern).


1. Protocol Architecture and Message Flows

Two-Phase Commit coordinates consensus through a designated Coordinator node interacting with multiple Cohort (Participant) nodes.

Two-Phase Commit Message Sequence:
   Coordinator                            Cohort 1                         Cohort 2
        |                                    |                                |
        | ----- 1. PREPARE (TxnID) --------> |                                |
        | ------------------------------------------------------------------> |
        |                                    | (Acquires locks, writes WAL)   | (Acquires locks, writes WAL)
        | <---- 2. VOTE_COMMIT --------------|                                |
        | <------------------------------------------------------------------ |
        |                                    |                                |
[ All Voted COMMIT ]                         |                                |
        |                                    |                                |
        | ===== 3. GLOBAL_COMMIT ===========> |                                |
        | ==================================================================> |
        |                                    | (Commits locks, frees res)     | (Commits locks, frees res)
        | <---- 4. ACK_COMMIT ---------------|                                |
        | <------------------------------------------------------------------ |
[ Txn Finished ]                             |                                |

2. Phase-by-Phase State Machine Breakdown

+-------------------------------------------------------------------------------+
|                       2PC PROTOCOL STATE TRANSITIONS                          |
+-------------------------------------------------------------------------------+
| PHASE 1: Prepare Phase (Voting Phase)                                         |
| 1. Coordinator writes `START_2PC` to Write-Ahead Log (WAL).                   |
| 2. Coordinator broadcasts `PREPARE` messages to all Cohorts.                 |
| 3. Cohorts execute transaction locally, acquire exclusive row/table locks,   |
|    write redo/undo logs to persistent storage, and reply `VOTE_COMMIT`.       |
| 4. If any cohort fails or times out, it replies `VOTE_ABORT`.                |
|                                                                               |
| PHASE 2: Commit Phase (Resolution Phase)                                      |
| 1. If ALL cohorts vote `VOTE_COMMIT`:                                         |
|    - Coordinator writes `COMMIT` to its WAL and broadcasts `GLOBAL_COMMIT`.   |
|    - Cohorts apply mutations permanently, release locks, and reply `ACK`.     |
| 2. If ANY cohort voted `VOTE_ABORT` or timed out:                             |
|    - Coordinator writes `ABORT` to its WAL and broadcasts `GLOBAL_ABORT`.     |
|    - Cohorts use undo logs to rollback, release locks, and reply `ACK`.       |
+-------------------------------------------------------------------------------+

3. Failure Recovery Scenarios and Edge Cases

+---------------------------+-----------------------------------+------------------------+
| Failure Point             | Cohort State                      | Recovery Resolution    |
+---------------------------+-----------------------------------+------------------------+
| Cohort crashes before     | Has not voted                     | Coordinator times out, |
| voting                    |                                   | broadcasts GLOBAL_ABORT|
| Cohort crashes after      | In "Prepared" state, locks held   | Recovers from WAL, asks|
| voting COMMIT             |                                   | coordinator for outcome|
| Coordinator crashes after | Cohorts in "Prepared" state,      | BLOCKING HAZARD:       |
| receiving all votes       | cannot commit or abort            | Cohorts blocked until  |
|                           | independently                     | coordinator recovers   |
+---------------------------+-----------------------------------+------------------------+

The Fundamental Flaw: Synchronous Blocking

The primary architectural limitation of 2PC is that it is a blocking protocol. If the Coordinator crashes immediately after Cohorts have voted VOTE_COMMIT and before broadcasting the decision:


4. Architectural Alternatives: 2PC vs. 3PC vs. Saga Pattern

+-----------------------------------------------------------------------------------------+
|                               DISTRIBUTED TRANSACTION MATRIX                            |
+-----------------------------------------------------------------------------------------+
| Protocol           | Consistency Model    | Latency Overhead    | Blocking Hazard | Complexity |
+--------------------+----------------------+---------------------+-----------------+------------+
| Two-Phase Commit   | Strict ACID (CP)     | High (2 Roundtrips) | Yes (Coord Fail)| Moderate   |
| Three-Phase Commit | Non-blocking ACID    | Very High (3 RTTs)  | No (PreCommit)  | Very High  |
| Saga Pattern       | Eventual Consistency | Low (Async Events)  | No (Compensate) | High       |
| **[MysticetiConsensus](MysticetiConsensus)** | DAG BFT Consensus   | Sub-Second (3 Delays)| No (Leaderless) | High       |
| Raft/Paxos Commit  | Consensus-backed 2PC | Moderate (2 RTTs)   | No (Quorum elec)| High       |
+-----------------------------------------------------------------------------------------+

The Saga Pattern (Compensating Transactions)

In modern microservice architectures, the Saga Pattern replaces synchronous 2PC locks with a sequence of local transactions coordinated via asynchronous events. If step N fails, the saga orchestrator executes compensating transactions (C_{N-1}, C_{N-2}, \dots, C_1) in reverse order to semantically undo preceding side-effects.


References

  1. Gray, J. (1978). Notes on Data Base Operating Systems. Operating Systems, An Advanced Course, Springer-Verlag, 393–481.
  2. Skeen, D. (1981). Nonblocking Commit Protocols. Proceedings of the 1981 ACM SIGMOD International Conference on Management of Data, 133–142.
  3. Garcia-Molina, H., & Salem, K. (1987). Sagas. ACM SIGMOD Record, 16(3), 249–259.
  4. Kleppmann, M. (2017). Designing Data-Intensive Applications. O'Reilly Media.