6 Distributed transactions
Distributed transactions span multiple resource managers and require atomic commitment so that all participants either commit or abort together. While a single resource manager can ensure atomicity with a single durable write, coordinating the all-or-nothing outcome across several managers demands an atomic commit protocol that provides safety (no conflicting outcomes) and, ideally, liveness (participants eventually decide). The chapter focuses on atomicity within ACID and contrasts blocking protocols—which always preserve safety but may stall under certain failures—with non-blocking ones that preserve both properties under limited failure scenarios. The most prominent protocol in practice is Two-Phase Commit (2PC), which is safe under failures but only live when the coordinator does not fail.
The essence of a distributed (global) transaction is that it is composed of multiple local transactions, each running on a different resource manager. Each local transaction moves through the states working, prepared, and then a final committed or aborted state. In the prepared state, work is finished locally and the participant is durably ready to follow the final decision. Conceptually, the global state consists of the vector of these local states plus any in-flight messages on the network—an important mental model when reasoning about correctness in the presence of concurrency, asynchrony, and failures.
2PC divides roles into a single coordinator and multiple resource managers and proceeds in two phases: the coordinator first collects votes (prepare) and then broadcasts the final decision (commit or abort). With durable logging at each step, 2PC ensures safety and, absent failures, liveness. The protocol tolerates resource manager failures without blocking: participants can recover by consulting their logs and the coordinator. However, if the coordinator fails after some participants have voted to commit, those participants can become blocked because they cannot infer the global decision. Variants attempt to reduce blocking—for example, allowing participants to query each other—but subtle timing and clock-skew scenarios can threaten safety, so these improvements lessen, but do not eliminate, 2PC’s inherent blocking behavior.
From a single RM to multiple RMs
How do we coordinate and guarantee multiple commits?
A distributed transaction consists of two or more non-distributed transactions.
State Machine of non-distributed transactions
Global transaction (outstanding messages not illustrated)
Two Phase Commit protocol
A resource manager fails before persistently recording ⟨Vote-To-Commit⟩ or ⟨Abort⟩.
A resource manager fails after persistently recording ⟨Vote-To-Commit⟩ or ⟨Abort⟩.
A resource manager fails after persistently recording ⟨Commit⟩.
A resource manager fails after persistently recording ⟨Abort⟩.
Failure of transaction coordinator after the first commit
Failure of transaction coordinator before the first commit
Summary
- Distributed transactions extend non-distributed transactions to span multiple resource managers.
- A distributed transaction, also referred to as a global transaction, consists of two or more non-distributed transactions, also referred to as local transactions.
- Atomic Commit Protocols ensure distributed transactions achieve a unanimous commit or abort decision, upholding atomicity across resource managers.
- Blocking commit protocols guarantee safety but not liveness in the presence of failure.
- Non-blocking commit protocols guarantee safety and liveness in the presence of failure.
- The Two-Phase Commit (2PC) protocol is the most well-known and the most well-studied atomic commit protocol.
- 2PC divides participants into a transaction coordinator and resource manager and operates in two phases: the Prepare Phase and the Commit Phase.
- 2PC guarantees safety and liveness in the case of a resource manager failure.
- 2PC guarantees safety in the case of the transaction coordinator failure.
FAQ
What is a distributed transaction and who participates in it?
A distributed transaction (global transaction) spans multiple systems. Each system that applies a portion of the changes is a resource manager (RM), such as a database or a message queue. The distributed transaction is composed of multiple local transactions, one per RM, that must all reach the same final outcome: commit or abort.
How is atomicity ensured on a single RM versus across multiple RMs?
On a single RM, atomicity is achieved by one durable log write of the final decision (commit or abort). If the RM crashes without a final record, it recovers as aborted. Across multiple RMs, atomicity requires an atomic commit protocol so that all local transactions either commit together or all abort.
What do safety and liveness mean for atomic commit protocols?
- Safety: No two participants reach conflicting outcomes—there cannot exist one RM that commits while another aborts the same transaction.
- Liveness: Every participant eventually reaches a final, irreversible decision (commit or abort), rather than waiting forever.
What is the difference between blocking and non-blocking commit protocols?
Blocking protocols guarantee safety but may lose liveness when some participant fails (others can be forced to wait indefinitely). Non-blocking protocols guarantee both safety and liveness in the presence of a single participant failure—one failure does not prevent others from deciding commit or abort.
How does the Two-Phase Commit (2PC) protocol work when there are no failures?
- Prepare Phase: The coordinator logs “Prepare,” asks all RMs to prepare. Each RM decides locally: if ready, it durably logs “Vote-to-Commit” and replies so; otherwise, it logs “Abort,” replies abort, and aborts locally.
- Commit Phase: If all votes are commit, the coordinator logs “Commit” and instructs all RMs to commit. If any RM aborts (or there is a timeout), the coordinator logs “Abort” and instructs all RMs to abort. Each RM then durably records and applies the final decision.
Why does 2PC use “Vote-to-Commit” and “Abort” (and not “Vote-to-Abort”) in the Prepare phase?
Commit requires unanimity and coordination, so an RM can only promise it is ready (“Vote-to-Commit”). Abort is always safe to decide unilaterally—any single RM can force the global outcome to be abort without risking a safety violation. Hence the asymmetry.
How does 2PC handle resource manager failures?
- RM fails before logging a vote: On recovery, it logs “Abort” and notifies the coordinator to abort.
- RM fails after logging “Vote-to-Commit”: On recovery, it must query the coordinator for the final decision (commit or abort).
- RM fails after logging “Commit”: On recovery, it REDOs the commit work.
- RM fails after logging “Abort”: On recovery, it UNDOs as needed to complete the abort.
Why can 2PC block if the transaction coordinator fails?
If RMs have voted to commit and the coordinator fails before sending the final decision to all of them, the RMs that only voted cannot safely choose commit or abort on their own—doing so risks a safety violation. They must wait for the coordinator to recover and announce the decision, which may block progress.
What improvements exist for 2PC, and why isn’t a simple timeout safe?
Variants reduce blocking by letting RMs consult each other: if any RM has a final decision (commit/abort), others can adopt it. However, if all RMs only voted and none received a final decision, using timeouts to decide can break safety because unsynchronized clocks may lead some RMs to abort while others later receive and act on a commit.
What are the states of a local transaction, and how do they compose into a global transaction?
- Working: Executing operations; may later prepare or abort.
- Prepared: Waiting for the coordinator’s final commit/abort instruction; no more local updates.
- Committed or Aborted: Final, irreversible state.
The global transaction’s state is the vector of all local states plus any in-flight protocol messages. Atomic commit protocols ensure this vector reaches a consistent all-commit or all-abort outcome.
Think Distributed Systems ebook for free