88 *
99 *
1010 * IDENTIFICATION
11- * $PostgreSQL: pgsql/src/backend/access/transam/transam.c,v 1.73 2008/01/01 19:45:48 momjian Exp $
11+ * $PostgreSQL: pgsql/src/backend/access/transam/transam.c,v 1.74 2008/03/11 20:20:35 tgl Exp $
1212 *
1313 * NOTES
1414 * This file contains the high level access-method interface to the
2525#include "utils/tqual.h"
2626
2727
28- static XidStatus TransactionLogFetch (TransactionId transactionId );
29- static void TransactionLogUpdate (TransactionId transactionId ,
30- XidStatus status ,XLogRecPtr lsn );
31-
3228/*
33- * Single-item cache for results of TransactionLogFetch.
29+ * Single-item cache for results of TransactionLogFetch. It's worth having
30+ * such a cache because we frequently find ourselves repeatedly checking the
31+ * same XID, for example when scanning a table just after a bulk insert,
32+ * update, or delete.
3433 */
3534static TransactionId cachedFetchXid = InvalidTransactionId ;
3635static XidStatus cachedFetchXidStatus ;
@@ -39,9 +38,14 @@ static XLogRecPtr cachedCommitLSN;
3938/* Handy constant for an invalid xlog recptr */
4039static const XLogRecPtr InvalidXLogRecPtr = {0 ,0 };
4140
41+ /* Local functions */
42+ static XidStatus TransactionLogFetch (TransactionId transactionId );
43+ static void TransactionLogUpdate (TransactionId transactionId ,
44+ XidStatus status ,XLogRecPtr lsn );
45+
4246
4347/* ----------------------------------------------------------------
44- *postgres log access method interface
48+ *Postgres log access method interface
4549 *
4650 *TransactionLogFetch
4751 *TransactionLogUpdate
@@ -82,8 +86,8 @@ TransactionLogFetch(TransactionId transactionId)
8286xidstatus = TransactionIdGetStatus (transactionId ,& xidlsn );
8387
8488/*
85- * DO NOT cache status for unfinished or sub-committed transactions! We
86- * only cache status that is guaranteed not to change.
89+ *Cache it, but DO NOT cache status for unfinished or sub-committed
90+ *transactions! We only cache status that is guaranteed not to change.
8791 */
8892if (xidstatus != TRANSACTION_STATUS_IN_PROGRESS &&
8993xidstatus != TRANSACTION_STATUS_SUB_COMMITTED )
@@ -96,12 +100,11 @@ TransactionLogFetch(TransactionId transactionId)
96100return xidstatus ;
97101}
98102
99- /* --------------------------------
103+ /*
100104 *TransactionLogUpdate
101105 *
102106 * Store the new status of a transaction. The commit record LSN must be
103107 * passed when recording an async commit; else it should be InvalidXLogRecPtr.
104- * --------------------------------
105108 */
106109static inline void
107110TransactionLogUpdate (TransactionId transactionId ,
@@ -131,32 +134,27 @@ TransactionLogMultiUpdate(int nxids, TransactionId *xids,
131134TransactionIdSetStatus (xids [i ],status ,lsn );
132135}
133136
137+
134138/* ----------------------------------------------------------------
135139 *Interface functions
136140 *
137- *TransactionId DidCommit
138- *TransactionId DidAbort
139- *TransactionId IsInProgress
141+ *TransactionIdDidCommit
142+ *TransactionIdDidAbort
140143 *========
141144 * these functions test the transaction status of
142145 * a specified transaction id.
143146 *
144- *TransactionId Commit
145- *TransactionId Abort
147+ *TransactionIdCommit
148+ *TransactionIdAbort
146149 *========
147150 * these functions set the transaction status
148151 * of the specified xid.
149152 *
153+ * See also TransactionIdIsInProgress, which once was in this module
154+ * but now lives in procarray.c.
150155 * ----------------------------------------------------------------
151156 */
152157
153- /* --------------------------------
154- *TransactionId DidCommit
155- *TransactionId DidAbort
156- *TransactionId IsInProgress
157- * --------------------------------
158- */
159-
160158/*
161159 * TransactionIdDidCommit
162160 *True iff transaction associated with the identifier did commit.
@@ -262,11 +260,33 @@ TransactionIdDidAbort(TransactionId transactionId)
262260return false;
263261}
264262
265- /* --------------------------------
266- *TransactionId Commit
267- *TransactionId Abort
268- * --------------------------------
263+ /*
264+ * TransactionIdIsKnownCompleted
265+ *True iff transaction associated with the identifier is currently
266+ *known to have either committed or aborted.
267+ *
268+ * This does NOT look into pg_clog but merely probes our local cache
269+ * (and so it's not named TransactionIdDidComplete, which would be the
270+ * appropriate name for a function that worked that way). The intended
271+ * use is just to short-circuit TransactionIdIsInProgress calls when doing
272+ * repeated tqual.c checks for the same XID. If this isn't extremely fast
273+ * then it will be counterproductive.
274+ *
275+ * Note:
276+ *Assumes transaction identifier is valid.
269277 */
278+ bool
279+ TransactionIdIsKnownCompleted (TransactionId transactionId )
280+ {
281+ if (TransactionIdEquals (transactionId ,cachedFetchXid ))
282+ {
283+ /* If it's in the cache at all, it must be completed. */
284+ return true;
285+ }
286+
287+ return false;
288+ }
289+
270290
271291/*
272292 * TransactionIdCommit
@@ -292,7 +312,6 @@ TransactionIdAsyncCommit(TransactionId transactionId, XLogRecPtr lsn)
292312TransactionLogUpdate (transactionId ,TRANSACTION_STATUS_COMMITTED ,lsn );
293313}
294314
295-
296315/*
297316 * TransactionIdAbort
298317 *Aborts the transaction associated with the identifier.
@@ -352,7 +371,6 @@ TransactionIdAsyncCommitTree(int nxids, TransactionId *xids, XLogRecPtr lsn)
352371lsn );
353372}
354373
355-
356374/*
357375 * TransactionIdAbortTree
358376 *Marks all the given transaction ids as aborted.
@@ -368,6 +386,7 @@ TransactionIdAbortTree(int nxids, TransactionId *xids)
368386InvalidXLogRecPtr );
369387}
370388
389+
371390/*
372391 * TransactionIdPrecedes --- is id1 logically < id2?
373392 */