A distributed commit is the problem of making N independent databases, queues, or services treat one transaction as atomic. The workhorse is two-phase commit (2PC), and here is exactly what executes, in order, with a coordinator C and participants P1…P3.
PREPARE to every participant in parallel. This is one RTT to each (0.5–5ms in a datacenter). The transaction work itself — the SQL, the queue enqueue — has already run at each participant, but nothing is final.YES (I am prepared, I can commit) or NO (I cannot — abort). A NO can come from a constraint violation, a deadlock timeout, or a failed local fsync. One NO anywhere means the whole transaction dies.COMMIT to its own log and fsyncs it. If any NO, C writes ABORT. This log record is the decision's source of truth — from now on, even if C crashes, recovery reads this record and drives the participants to the same outcome.COMMIT (or ABORT) to every participant. Each participant applies the transaction, writes the outcome to its log, and replies ACK. This is the second full RTT round. The transaction becomes visible at different participants at different milliseconds — atomicity means all eventually commit, not that they flip simultaneously.on PREPARE: run txn work → fsync PREPARED → reply YES/NO
on COMMIT: apply txn → fsync COMMITTED → reply ACK
on ABORT: rollback → fsync ABORTED → reply ACKThe honest cost sheet: 2PC adds roughly 2×RTT + 2×fsync over a single-node commit, it blocks on the slowest participant, and its failure mode is a stuck transaction, not a wrong one. The three-phase variant adds a preCommit round to shrink the blocking window but pays an extra RTT and still cannot survive a partition between two rounds — which is the deeper reason consensus protocols like Raft replace the coordinator instead of patching it.