Distributed systems
Part 4 of 6 · Two-Phase Commit — Protocol, Coordinator & ParticipantsOptimizations - Presumed Abort, Presumed Commit & Read-Only Votes
Presumed abort, presumed commit, and read-only votes without shrinking the uncertainty window.
- 1Gist
- 2Maps
- 3Q&A
- 4Sandbox
Voice readout needs Web Speech Synthesis in this browser.
Question ladder
L1
What does no coordinator record mean under presumed abort?
Answer
Abort. A missing record must not be a commit. COMMIT is still forced before it is sent to updaters.
L2
What can presumed abort skip?
Answer
A forced abort record, acks for abort, and any log at a read-only participant. It cannot skip the forced COMMIT for updaters.
L3
Why does presumed commit force a collecting record before PREPARE?
Answer
So a crash after PREPARE is distinguishable from never started. The former must abort and must know who to tell. The latter is the only state allowed to look like a forgotten commit.
L4
Does presumed abort let a prepared participant abort on silence?
Answer
No. The presumption is how the coordinator answers when it has no COMMIT record. Silence is not an answer.
L5
When is presumed commit the worse trade?
Answer
Fully read-only distributed transactions, and workloads whose aborts are frequent. Presumed commit still pays for the collecting record and for forced abort handling.
L6
Can a read-only voter disagree with the global decision?
Answer
Not by writes, because it has none. It can be part of an isolation anomaly if it dropped read locks that strict two-phase locking still needed.
L7
Which presumption do Postgres-style coordinators usually match?
Answer
Engines that roll back when the transaction manager has no commit record are in the presumed-abort family. Do not assume presumed commit unless you have seen a collecting record and commit-on-no-information.
Failure modes
Presumed commit without a collecting record
A coordinator that crashes before PREPARE, forgets the transaction, and is later asked by someone who did prepare from RAM will answer COMMIT while another participant aborted.
Skipping the coordinator fsync because commit is presumed
The root still has force points. You moved forces. You did not delete the decision.
Read-only optimization under strict two-phase locking
Releasing read locks at prepare time lets a concurrent writer change a row before the global decision.
Participant presumes on its own
A prepared updater that applies the coordinator's presumption without an answer is back inside the uncertainty window.
Misconceptions
Presumed abort makes 2PC non-blocking.
A prepared updater still waits. The presumption only changes how a coordinator answers an inquiry and which records it must force.
READ-ONLY is a weak YES and still needs phase 2.
There is no redo. Phase 2 messages to that participant are overhead. It is also not a veto of the updaters.
Presumed commit is always cheaper.
It makes the commit ack path cheaper and makes completely read-only transactions more expensive than presumed abort.
Interviewer traps
Read-only optimization with no isolation clause.
Snapshot isolation can release readers because the snapshot is already fixed. Strict two-phase locking cannot release those read locks early.
Calling these optimizations a saga.
Compensations are a different contract. Point at the existing 2PC versus sagas page and stay on log presumptions.
Design scenario
Same prompt for every reader.
Requirements
Readers leave without a second log force. A real commit of updaters is still forced before COMMIT is sent. A prepared updater still blocks if the coordinator is down.
Traffic / scale
Mostly remote reads, with a thin tail of two-shard updates.
Latency
A read-only cohort pays no phase 2. An updating commit still pays the coordinator force.
Consistency
Same atomic commit as basic 2PC. Isolation matches the engine, stated out loud.
Availability
Abort paths do not wait for acks. Prepared updaters still stall when the decision is unknown.
Failure assumptions
- The coordinator can crash after a NO and before any abort record is forced.
- A participant can inquire after the coordinator has forgotten the transaction.
Constraints
- Do not implement no-record-means-commit without a collecting record.
- Do not drop read locks early under a protocol that needed them until the global commit.
Prompt
Most distributed transactions on this shard are read-only, and aborts from constraint failures are common. Updating commits are rare but must stay atomic.
API
Which votes are omitted from the COMMIT list?
Data
What does an empty coordinator log answer under the presumption you picked?
Architecture
Where is the collecting record if you chose presumed commit, and who forces it?
Which missing record is cheap
Prefer
Presumed abort as the default
Aborts and read-only leaves are common. No COMMIT record means abort, so those paths skip forces and acks. Updating commits still force the decision.
- A completely read-only transaction writes nothing and has no phase 2.
- Restart that finds no COMMIT answers abort.
- A prepared updater still cannot presume alone.
Alternative
Presumed commit when updates usually commit
Participants can skip a forced commit record and commit acks. The coordinator pays a forced collecting record before any PREPARE, and abort becomes the expensive path.
- No information at all answers COMMIT.
- Collecting with no later record aborts.
- Read-only cohorts still pay for the collecting record.
Pick the presumption from the log you will actually write
Both protocols keep atomic commit. They move forces. They do not delete the decision.
- 1
Name the common outcome
If aborts and remote reads dominate, presumed abort makes those paths cheap. If updaters usually commit, presumed commit saves participant commit forces. - 2
Write the record that makes the presumption true
Presumed abort forces COMMIT before sending it. Presumed commit forces a collecting record naming subordinates before any PREPARE. - 3
Let read-only participants leave
No redo means no PREPARED record and no phase 2 message. Keep read locks only as long as the isolation level requires. - 4
Leave the uncertainty window alone
A prepared updater still waits for a real answer. Silence is not abort under presumed abort, and it is not commit under presumed commit.
Overview
Basic 2PC force-writes too much, especially on abort and on read-only participants. Presumed abort (PA) and presumed commit (PC), from Mohan, Lindsay, and Obermarck's R-star work, change what a missing log means so the common path does fewer forces and fewer acks. They do not shrink the uncertainty window and they do not make 2PC non-blocking. Read-only votes are the other win: a participant with nothing to redo leaves before phase 2.
The presumption
On recovery the coordinator is asked what happened to transaction T, and sometimes it has no record.
| Protocol | No record means | You can skip | You must not skip |
|---|---|---|---|
| Presumed abort | ABORT | Forced abort records, acks for abort, any log at a read-only participant | Forced COMMIT before sending COMMIT to updaters. A missing record must not be a commit |
| Presumed commit | COMMIT, only in the no-information case after the extra record rules | Participant forced commit records, acks for commit | A forced collecting record naming subordinates before PREPARE. Forced abort records and abort acks |
If you implement "no record means commit" without the collecting record, a coordinator that crashes before PREPARE, forgets the transaction, and is later asked by a participant that did prepare (because you sent PREPARE from RAM) will say COMMIT while another participant aborted. The collecting record makes that conversation impossible. If PREPARE went out, the collecting record is durable, so recovery that sees collecting and nothing else aborts and knows who to tell.
Presumed abort
This is what most database engines mean when they say 2PC.
Coordinator:
- Does not need a forced start record for the abort optimization. Implementations still track participants in memory and often log them.
- On all-YES from updaters: force a COMMIT record that lists those participants, send COMMIT, wait for acks, then forget. END need not be forced.
- On NO or timeout: write ABORT without forcing, send ABORT, do not wait for acks, forget immediately. Restart that finds no COMMIT record answers ABORT. Resending ABORT is idempotent.
- Completely read-only transaction: no commit record and no abort record. Everyone voted read-only. Missing record means abort, and abort of a read-only transaction is a no-op, so there is no second phase at all.
Participant with updates:
- Force PREPARED before YES, as in basic 2PC.
- On COMMIT: force a commit record and ack. The participant must not forget a commit it has applied if the ack is lost.
- On abort after having prepared: undo. The coordinator is the one that presumes abort when asked. A prepared participant does not presume on its own. PA did not repeal blocking.
Participant read-only:
- Sends READ-ONLY.
- Writes no PREPARED record.
- Releases its read locks subject to the isolation note below.
- Is absent from the COMMIT list.
PA is the right default because aborts and read-only leaves are common, and the expensive force stays on the true commit path.
Presumed commit
PC makes the commit ack path cheaper and makes completely read-only transactions more expensive. For a coordinator process, the R-star shape is:
- Before sending any PREPARE, force-write a collecting record naming every subordinate. The state becomes collecting.
- If it must abort after that record exists, it force-writes ABORT, sends ABORT, waits for acks, writes END, and forgets.
- If it commits, the root force-writes COMMIT as well in the paper's root rule. Acks are required for ABORT, not for COMMIT.
- Recovery that finds a collecting record and no later record force-writes ABORT and runs the abort protocol. That state is not presumed commit.
- Recovery that finds no information at all answers COMMIT to an inquiry.
Step 5 is safe because a participant only asks if it prepared, and it could only have been asked to prepare after the collecting record was forced. So "no information" means the coordinator finished and forgot a commit, not "the coordinator never started." The dangerous half-start still has a collecting record, and that state aborts.
Subordinates in PC force-write abort, not commit, and ack abort, not commit. Losing a COMMIT message is recovered by inquiry, and the inquiry returns COMMIT once the coordinator has forgotten the transaction.
Completely read-only under PC is clumsier than PA. The coordinator still pays for the forced collecting record, then writes a non-forced commit record to forget. PA pays nothing. If your workload is mostly read-only distributed transactions, PA wins. If you have many updating participants and commit is the common outcome, PC saves participant log forces.
Read-only votes
A participant may vote READ-ONLY only if it has no updates that need redo or undo. Then:
- It cannot be inconsistent with a later global commit or abort, because it has no dirty writes.
- Phase 2 messages to it are overhead.
- PA plus read-only is why a distributed read does not pay two log forces.
Isolation caveat: if the participant released read locks at PREPARE time, a concurrent writer can change a row the transaction read before the global decision. Under strict two-phase locking that release is early and can break serializability of the distributed transaction. Snapshot-isolation and MVCC engines often do not need those read locks to stay until commit, because the snapshot is already chosen. Say which one you mean. "Read-only optimization" without an isolation clause is a trap answer.
Early prepare is the same vote, overlapped with later application work. The vote is still a prepare. It is not a commit.
Decisions
- 1
1. Local work is finished
- next2. Any updates?
- ?
2. Any updates?
- no3. READ-ONLY, skip phase 2
- yes4. Force PREPARED, then YES
- 3
3. READ-ONLY, skip phase 2
- 4
4. Force PREPARED, then YES
- next5. Coordinator log
- ?
5. Coordinator log
- COMMIT6. Commit path for this protocol
- PA, no COMMIT7. Abort, ABORT may be unforced
- PC collecting8. Collecting alone is abort
- 6
6. Commit path for this protocol
- 7
7. Abort, ABORT may be unforced
- 8
8. Collecting alone is abort
Lesson map
Presumed abort and read-only
The reader has left. The updater is locked on YES. The coordinator has no COMMIT record.
Architecture. Coordinator No COMMIT. Updater Locked · YES. Reader Left
Select a node to see why it exists, or an edge to see the protocol, direction, effect, and consequence.
Mermaid export
flowchart TB coordinator["Coordinator No COMMIT"] updater["Updater Locked YES"] reader["Reader Left"] coordinator -->|PREPARE| updater coordinator -->|PREPARE| reader reader -->|READ-ONLY| coordinator updater -->|YES| coordinator updater -->|Lock held| coordinator coordinator -->|Unforced ABORT| updater coordinator -->|No record| updater coordinator -->|Not PC| reader
What these optimizations do not buy
- They do not let a prepared updater decide alone.
- They do not fix a lost coordinator disk. That case is still on failures and recovery.
- They do not turn 2PC into a saga. Compensations are a different contract. The existing comparison is Two-Phase Commit vs Sagas.
- They do not remove the need to list participants somewhere durable before you can finish a commit those participants must apply.
Choosing PC because "commit is presumed, so we can skip fsync on the coordinator" is the classic mis-implementation. The root still has force points: collecting, and commit at the root in the published protocol. You moved forces. You did not delete the decision.
Comparison you can say out loud
| Basic 2PC | Presumed abort | Presumed commit | |
|---|---|---|---|
| Missing coordinator info | Usually abort if there is no commit record | Abort | Commit |
| Extra record before PREPARE | Start, often forced | Not required for the presumption | Collecting record, forced |
| Abort force and ack wait | Yes | No | Yes |
| Commit force at the coordinator | Yes | Yes | Yes at the root |
| Read-only cost | Easy to make as expensive as an updater | No log, no phase 2 | Still pays collecting at the coordinator |
| Blocking if an updater is prepared and the TM is down | Yes | Yes | Yes |
Sandbox
The presumption is a function of the log.
Press Run. Snippets must be self-contained — no network, files, or native modules.
Press Run. Snippets must be self-contained — no network, files, or native modules.
Pitfalls
- Implementing presumed commit without the collecting record is a correctness bug, not a faster commit.
- Dropping a read-only participant from phase 2 is about redo, not about every isolation level.
- These shortcuts are not the saga boundary. Keep that on the existing comparison page.
Interview Q&A
Does presumed abort mean a prepared participant can abort if it hears nothing?
Answer
No. The presumption is how the coordinator answers when it has no COMMIT record. The participant still needs that answer, or an ABORT message. Silence is not an answer.
Why does presumed commit force a collecting record before PREPARE?
Answer
So a crash after PREPARE is distinguishable from never started. The former must abort and must know the participant list. The latter is the only state allowed to look like a forgotten commit.
When is presumed commit a bad trade?
Answer
Fully read-only distributed transactions, and any workload whose aborts are frequent, because PC forces abort handling and the collecting record while PA makes abort and read-only cheap. It is also a bad trade if you might forget the collecting record. The optimization becomes a correctness bug.
Can a read-only voter be inconsistent with the global decision?
Answer
Not via writes, because it has none. It can be part of an isolation anomaly if it dropped read locks early under a protocol that needed them until the global commit. Atomicity and isolation are different questions.
Which presumption does Postgres-style XA usually line up with?
Answer
Engines that treat "no commit record at the transaction manager, so roll back" are in the presumed-abort family. Confirm in the transaction manager you actually run. Do not assume presumed commit unless you have seen a collecting record and commit-on-no-information. The engine surface is on XA.
Why can a completely read-only transaction skip phase 2 under presumed abort?
Answer
Everyone voted read-only, so there is nothing to redo. A missing record means abort, and abort of a read-only transaction is a no-op. No commit record is required.
What is early prepare?
Answer
A participant may force PREPARED as soon as its own work finishes, overlapping that force with later work at other participants. The vote is still a prepare. It does not commit the global transaction.
Do these optimizations remove blocking when the coordinator disk is lost?
Answer
No. A prepared updater still has no safe local choice. Presumptions change inquiries and log traffic. They do not invent a decision the disk no longer holds. Compensations, if that is the product contract, stay on Two-Phase Commit vs Sagas.
Write two coordinator logs on paper: empty, and a collecting record with no commit. Answer both logs once as presumed abort and once as presumed commit. Only one of the four answers is commit, and it is the empty log under presumed commit.
Go deeper
- Mohan, Lindsay, and Obermarck, Transaction Management in the R-star Distributed Database Management System.
- Adrian Colyer on presumed abort and presumed commit.
- Bernstein, Hadzilacos, and Goodman on optimizations of 2PC.
- CMU 15-445 on early prepare and read-only participants.