Two-Phase Commit: Prepare, Global Decisions, and Blocking
How 2PC prepares participants, distributes a global decision, and can leave prepared work waiting during coordinator failure.
Publication & corrections: infostoa · Editorial standards
Individual author and specialist reviewer information is not provided for this article.
When one business operation spans multiple databases, a partial commit can leave an order and its payment in different states. Two-phase commit (2PC) asks participants to prepare first, then has a coordinator distribute a global decision. It helps coordinate all-or-nothing outcomes, but recovery state must be managed and participants may wait during failures.
When atomic commit matters
A distributed transaction coordinates changes across independent resources as one business operation. If separate stores each record part of an order, committing only one side can leave inconsistent data that is difficult to reconcile. 2PC aims to commit everywhere only when every participant agrees it can do so; if preparation fails, the coordinator directs an abort. This is a protocol for coordinating a decision, not a promise that every application operation will be reversible.
What participants promise during prepare
The coordinator asks each participant whether it can commit the change. A participant records enough prepared state and durable recovery information to continue after a restart, then votes yes or no. Martin Fowler’s pattern description notes that participants acquire resources they need, such as locks. A yes vote is not a final commit: it is a promise to commit if the global decision says so.
Global commit and abort decisions
If every participant votes yes, the coordinator sends commit and each participant finalizes its change. A no vote leads to an abort decision. In PostgreSQL, PREPARE TRANSACTION stores a transaction outside the issuing session; COMMIT PREPARED or ROLLBACK PREPARED later resolves it. PostgreSQL documents this as support for an external transaction manager and as a PostgreSQL-specific extension, not as a universal SQL command set.
Coordinator failure and the meaning of blocking
If a coordinator becomes unavailable after participants have durably prepared, they may not know whether the global decision is commit or abort. They can retain prepared state and locks while waiting, preserving consistency at the cost of progress. This is the blocking problem; it does not mean a permanent deadlock must always occur. Durable coordinator logs, recovery, and redelivery can restore a decision after restart. If both the decision maker and network state are uncertain, a participant cannot safely invent a different global outcome on its own.
Expert perspective: plan for held resources and recovery
PostgreSQL warns that long-lived prepared transactions keep locks, interfere with VACUUM reclaiming storage, and in extreme cases can contribute to transaction-ID wraparound shutdown protection. Operations therefore need a way to track unresolved transactions and have an external manager close them promptly. A Saga may fit workflows that need compensating actions across services, but compensation is not the same as atomic rollback; its business effects must be designed explicitly.
Questions for an implementation review
Check whether each participant’s prepared record survives a crash, whether repeating a coordinator decision is safe, and whether unresolved transactions have alerts and a recovery owner. If using PostgreSQL, heed its warning to enable prepared transactions only when an external manager tracks and resolves them promptly. The tradeoff depends on consistency needs and on each resource’s capabilities.
During recovery, reconcile each participant’s durable log with the coordinator’s decision log to identify prepared, committed, or aborted state; operators should not guess after a restart. PostgreSQL’s pg_prepared_xacts view can be compared with the external manager’s records to find missing or long-lived work. Verify that each resource handles redelivered decisions idempotently.
Sources
- PostgreSQL 16, PREPARE TRANSACTION — prepared state, resolution commands, external transaction-manager purpose, and cautions about transactions left open. PostgreSQL-specific implementation documentation.
- Unmesh Joshi, Two-Phase Commit (2023) — practitioner description of prepare/commit voting and durable participant decisions.