Skip to content

Commit af3855c

Browse files
Improve TransactionIdDidAbort() documentation.
Document that TransactionIdDidAbort() won't indicate that transactions that were in-progress during a crash have aborted. Tie this to existing discussion of the TransactionIdDidCommit() and TransactionIdDidCommit() protocol that code in heapam_visibility.c (and a few other places) must observe. Follow-up to bugfix commit eb5ad4f. Author: Peter Geoghegan <pg@bowt.ie> Reviewed-By: Andres Freund <andres@anarazel.de> Discussion: https://postgr.es/m/CAH2-Wzn4bEEqgmaUQL3aJ73yM9gAeK-wE4ngi7kjRjLztb+P0w@mail.gmail.com
1 parent 8bf6ec3 commit af3855c

File tree

2 files changed

+26
-16
lines changed

2 files changed

+26
-16
lines changed

src/backend/access/heap/heapam_visibility.c

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -11,21 +11,24 @@
1111
* shared buffer content lock on the buffer containing the tuple.
1212
*
1313
* NOTE: When using a non-MVCC snapshot, we must check
14-
* TransactionIdIsInProgress (which looks in the PGPROC array)
15-
* before TransactionIdDidCommit/TransactionIdDidAbort (which look in
16-
* pg_xact). Otherwise we have a race condition: we might decide that a
17-
* just-committed transaction crashed, because none of the tests succeed.
18-
* xact.c is careful to record commit/abort in pg_xact before it unsets
19-
* MyProc->xid in the PGPROC array. That fixes that problem, but it
20-
* also means there is a window where TransactionIdIsInProgress and
21-
* TransactionIdDidCommit will both return true. If we check only
22-
* TransactionIdDidCommit, we could consider a tuple committed when a
23-
* later GetSnapshotData call will still think the originating transaction
24-
* is in progress, which leads to application-level inconsistency. The
25-
* upshot is that we gotta check TransactionIdIsInProgress first in all
26-
* code paths, except for a few cases where we are looking at
27-
* subtransactions of our own main transaction and so there can't be any
28-
* race condition.
14+
* TransactionIdIsInProgress (which looks in the PGPROC array) before
15+
* TransactionIdDidCommit (which look in pg_xact). Otherwise we have a race
16+
* condition: we might decide that a just-committed transaction crashed,
17+
* because none of the tests succeed. xact.c is careful to record
18+
* commit/abort in pg_xact before it unsets MyProc->xid in the PGPROC array.
19+
* That fixes that problem, but it also means there is a window where
20+
* TransactionIdIsInProgress and TransactionIdDidCommit will both return true.
21+
* If we check only TransactionIdDidCommit, we could consider a tuple
22+
* committed when a later GetSnapshotData call will still think the
23+
* originating transaction is in progress, which leads to application-level
24+
* inconsistency. The upshot is that we gotta check TransactionIdIsInProgress
25+
* first in all code paths, except for a few cases where we are looking at
26+
* subtransactions of our own main transaction and so there can't be any race
27+
* condition.
28+
*
29+
* We can't use TransactionIdDidAbort here because it won't treat transactions
30+
* that were in progress during a crash as aborted. We determine that
31+
* transactions aborted/crashed through process of elimination instead.
2932
*
3033
* When using an MVCC snapshot, we rely on XidInMVCCSnapshot rather than
3134
* TransactionIdIsInProgress, but the logic is otherwise the same: do not

src/backend/access/transam/transam.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,8 @@ TransactionLogFetch(TransactionId transactionId)
110110
* transaction tree.
111111
*
112112
* See also TransactionIdIsInProgress, which once was in this module
113-
* but now lives in procarray.c.
113+
* but now lives in procarray.c, as well as comments at the top of
114+
* heapam_visibility.c that explain how everything fits together.
114115
* ----------------------------------------------------------------
115116
*/
116117

@@ -176,6 +177,12 @@ TransactionIdDidCommit(TransactionId transactionId)
176177
*
177178
* Note:
178179
* Assumes transaction identifier is valid and exists in clog.
180+
*
181+
* Returns true only for explicitly aborted transactions, as transactions
182+
* implicitly aborted due to a crash will commonly still appear to be
183+
* in-progress in the clog. Most of the time TransactionIdDidCommit(),
184+
* with a preceding TransactionIdIsInProgress() check, should be used
185+
* instead of TransactionIdDidAbort().
179186
*/
180187
bool /* true if given transaction aborted */
181188
TransactionIdDidAbort(TransactionId transactionId)

0 commit comments

Comments
 (0)