]> granicus.if.org Git - postgresql/commitdiff
Make TransactionIdIsInProgress check transam.c's single-item XID status cache
authorTom Lane <tgl@sss.pgh.pa.us>
Tue, 11 Mar 2008 20:20:35 +0000 (20:20 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Tue, 11 Mar 2008 20:20:35 +0000 (20:20 +0000)
before it goes groveling through the ProcArray.  In situations where the same
recently-committed transaction ID is checked repeatedly by tqual.c, this saves
a lot of shared-memory searches.  And it's cheap enough that it shouldn't
hurt noticeably when it doesn't help.
Concept and patch by Simon, some minor tweaking and comment-cleanup by Tom.

src/backend/access/transam/transam.c
src/backend/storage/ipc/procarray.c
src/include/access/transam.h

index 43aed75ad00e80a505329ab3c6311dcb3e9612ab..4c0cb4baf691d0ce26fdb5e224ed461fd8200dc1 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/access/transam/transam.c,v 1.73 2008/01/01 19:45:48 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/access/transam/transam.c,v 1.74 2008/03/11 20:20:35 tgl Exp $
  *
  * NOTES
  *       This file contains the high level access-method interface to the
 #include "utils/tqual.h"
 
 
-static XidStatus TransactionLogFetch(TransactionId transactionId);
-static void TransactionLogUpdate(TransactionId transactionId,
-                                        XidStatus status, XLogRecPtr lsn);
-
 /*
- * Single-item cache for results of TransactionLogFetch.
+ * Single-item cache for results of TransactionLogFetch.  It's worth having
+ * such a cache because we frequently find ourselves repeatedly checking the
+ * same XID, for example when scanning a table just after a bulk insert,
+ * update, or delete.
  */
 static TransactionId cachedFetchXid = InvalidTransactionId;
 static XidStatus cachedFetchXidStatus;
@@ -39,9 +38,14 @@ static XLogRecPtr cachedCommitLSN;
 /* Handy constant for an invalid xlog recptr */
 static const XLogRecPtr InvalidXLogRecPtr = {0, 0};
 
+/* Local functions */
+static XidStatus TransactionLogFetch(TransactionId transactionId);
+static void TransactionLogUpdate(TransactionId transactionId,
+                                        XidStatus status, XLogRecPtr lsn);
+
 
 /* ----------------------------------------------------------------
- *             postgres log access method interface
+ *             Postgres log access method interface
  *
  *             TransactionLogFetch
  *             TransactionLogUpdate
@@ -82,8 +86,8 @@ TransactionLogFetch(TransactionId transactionId)
        xidstatus = TransactionIdGetStatus(transactionId, &xidlsn);
 
        /*
-        * DO NOT cache status for unfinished or sub-committed transactions! We
-        * only cache status that is guaranteed not to change.
+        * Cache it, but DO NOT cache status for unfinished or sub-committed
+        * transactions!  We only cache status that is guaranteed not to change.
         */
        if (xidstatus != TRANSACTION_STATUS_IN_PROGRESS &&
                xidstatus != TRANSACTION_STATUS_SUB_COMMITTED)
@@ -96,12 +100,11 @@ TransactionLogFetch(TransactionId transactionId)
        return xidstatus;
 }
 
-/* --------------------------------
+/*
  *             TransactionLogUpdate
  *
  * Store the new status of a transaction.  The commit record LSN must be
  * passed when recording an async commit; else it should be InvalidXLogRecPtr.
- * --------------------------------
  */
 static inline void
 TransactionLogUpdate(TransactionId transactionId,
@@ -131,32 +134,27 @@ TransactionLogMultiUpdate(int nxids, TransactionId *xids,
                TransactionIdSetStatus(xids[i], status, lsn);
 }
 
+
 /* ----------------------------------------------------------------
  *                                             Interface functions
  *
- *             TransactionId DidCommit
- *             TransactionId DidAbort
- *             TransactionId IsInProgress
+ *             TransactionIdDidCommit
+ *             TransactionIdDidAbort
  *             ========
  *                these functions test the transaction status of
  *                a specified transaction id.
  *
- *             TransactionId Commit
- *             TransactionId Abort
+ *             TransactionIdCommit
+ *             TransactionIdAbort
  *             ========
  *                these functions set the transaction status
  *                of the specified xid.
  *
+ * See also TransactionIdIsInProgress, which once was in this module
+ * but now lives in procarray.c.
  * ----------------------------------------------------------------
  */
 
-/* --------------------------------
- *             TransactionId DidCommit
- *             TransactionId DidAbort
- *             TransactionId IsInProgress
- * --------------------------------
- */
-
 /*
  * TransactionIdDidCommit
  *             True iff transaction associated with the identifier did commit.
@@ -262,11 +260,33 @@ TransactionIdDidAbort(TransactionId transactionId)
        return false;
 }
 
-/* --------------------------------
- *             TransactionId Commit
- *             TransactionId Abort
- * --------------------------------
+/*
+ * TransactionIdIsKnownCompleted
+ *             True iff transaction associated with the identifier is currently
+ *             known to have either committed or aborted.
+ *
+ * This does NOT look into pg_clog but merely probes our local cache
+ * (and so it's not named TransactionIdDidComplete, which would be the
+ * appropriate name for a function that worked that way).  The intended
+ * use is just to short-circuit TransactionIdIsInProgress calls when doing
+ * repeated tqual.c checks for the same XID.  If this isn't extremely fast
+ * then it will be counterproductive.
+ *
+ * Note:
+ *             Assumes transaction identifier is valid.
  */
+bool
+TransactionIdIsKnownCompleted(TransactionId transactionId)
+{
+       if (TransactionIdEquals(transactionId, cachedFetchXid))
+       {
+               /* If it's in the cache at all, it must be completed. */
+               return true;
+       }
+
+       return false;
+}
+
 
 /*
  * TransactionIdCommit
@@ -292,7 +312,6 @@ TransactionIdAsyncCommit(TransactionId transactionId, XLogRecPtr lsn)
        TransactionLogUpdate(transactionId, TRANSACTION_STATUS_COMMITTED, lsn);
 }
 
-
 /*
  * TransactionIdAbort
  *             Aborts the transaction associated with the identifier.
@@ -352,7 +371,6 @@ TransactionIdAsyncCommitTree(int nxids, TransactionId *xids, XLogRecPtr lsn)
                                                                  lsn);
 }
 
-
 /*
  * TransactionIdAbortTree
  *             Marks all the given transaction ids as aborted.
@@ -368,6 +386,7 @@ TransactionIdAbortTree(int nxids, TransactionId *xids)
                                                                  InvalidXLogRecPtr);
 }
 
+
 /*
  * TransactionIdPrecedes --- is id1 logically < id2?
  */
index 575b138c435b3ddf49e53b0bef8fc207cb4e0cb8..d7ba39bc5d4dd595030a914fdf564b7b816d9385 100644 (file)
@@ -23,7 +23,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/storage/ipc/procarray.c,v 1.40 2008/01/09 21:52:36 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/storage/ipc/procarray.c,v 1.41 2008/03/11 20:20:35 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -60,6 +60,7 @@ static ProcArrayStruct *procArray;
 
 /* counters for XidCache measurement */
 static long xc_by_recent_xmin = 0;
+static long xc_by_known_xact = 0;
 static long xc_by_my_xact = 0;
 static long xc_by_latest_xid = 0;
 static long xc_by_main_xid = 0;
@@ -68,6 +69,7 @@ static long xc_no_overflow = 0;
 static long xc_slow_answer = 0;
 
 #define xc_by_recent_xmin_inc()                (xc_by_recent_xmin++)
+#define xc_by_known_xact_inc()         (xc_by_known_xact++)
 #define xc_by_my_xact_inc()                    (xc_by_my_xact++)
 #define xc_by_latest_xid_inc()         (xc_by_latest_xid++)
 #define xc_by_main_xid_inc()           (xc_by_main_xid++)
@@ -79,6 +81,7 @@ static void DisplayXidCache(void);
 #else                                                  /* !XIDCACHE_DEBUG */
 
 #define xc_by_recent_xmin_inc()                ((void) 0)
+#define xc_by_known_xact_inc()         ((void) 0)
 #define xc_by_my_xact_inc()                    ((void) 0)
 #define xc_by_latest_xid_inc()         ((void) 0)
 #define xc_by_main_xid_inc()           ((void) 0)
@@ -353,6 +356,17 @@ TransactionIdIsInProgress(TransactionId xid)
                return false;
        }
 
+       /*
+        * We may have just checked the status of this transaction, so if it is
+        * already known to be completed, we can fall out without any access to
+        * shared memory.
+        */
+       if (TransactionIdIsKnownCompleted(xid))
+       {
+               xc_by_known_xact_inc();
+               return false;
+       }
+
        /*
         * Also, we can handle our own transaction (and subtransactions) without
         * any access to shared memory.
@@ -1335,8 +1349,9 @@ static void
 DisplayXidCache(void)
 {
        fprintf(stderr,
-                       "XidCache: xmin: %ld, myxact: %ld, latest: %ld, mainxid: %ld, childxid: %ld, nooflo: %ld, slow: %ld\n",
+                       "XidCache: xmin: %ld, known: %ld, myxact: %ld, latest: %ld, mainxid: %ld, childxid: %ld, nooflo: %ld, slow: %ld\n",
                        xc_by_recent_xmin,
+                       xc_by_known_xact,
                        xc_by_my_xact,
                        xc_by_latest_xid,
                        xc_by_main_xid,
index 1887f9d0ab361a1346f0a8d2e5278e5b465bdba7..232c59cad3c231b939f1cb9a3d825b6684256a85 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/access/transam.h,v 1.64 2008/01/01 19:45:56 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/access/transam.h,v 1.65 2008/03/11 20:20:35 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -138,6 +138,7 @@ extern VariableCache ShmemVariableCache;
  */
 extern bool TransactionIdDidCommit(TransactionId transactionId);
 extern bool TransactionIdDidAbort(TransactionId transactionId);
+extern bool TransactionIdIsKnownCompleted(TransactionId transactionId);
 extern void TransactionIdCommit(TransactionId transactionId);
 extern void TransactionIdAsyncCommit(TransactionId transactionId, XLogRecPtr lsn);
 extern void TransactionIdAbort(TransactionId transactionId);