From 1b3d400cac138c12dd3d1428a9da112b69ad0f15 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Sun, 23 Sep 2007 18:50:38 +0000 Subject: [PATCH] TransactionIdIsInProgress can skip scanning the ProcArray if the target XID is later than latestCompletedXid, per Florian Pflug. Also some minor improvements in the XIDCACHE_DEBUG code --- make sure each call of TransactionIdIsInProgress is counted one way or another. --- src/backend/storage/ipc/procarray.c | 34 ++++++++++++++++++++++++----- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/src/backend/storage/ipc/procarray.c b/src/backend/storage/ipc/procarray.c index dbac4a8fd0..90ba09d5a8 100644 --- a/src/backend/storage/ipc/procarray.c +++ b/src/backend/storage/ipc/procarray.c @@ -23,7 +23,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/storage/ipc/procarray.c,v 1.34 2007/09/21 17:36:53 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/storage/ipc/procarray.c,v 1.35 2007/09/23 18:50:38 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -61,14 +61,18 @@ static ProcArrayStruct *procArray; /* counters for XidCache measurement */ static long xc_by_recent_xmin = 0; static long xc_by_my_xact = 0; +static long xc_by_latest_xid = 0; static long xc_by_main_xid = 0; static long xc_by_child_xid = 0; +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_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++) #define xc_by_child_xid_inc() (xc_by_child_xid++) +#define xc_no_overflow_inc() (xc_no_overflow++) #define xc_slow_answer_inc() (xc_slow_answer++) static void DisplayXidCache(void); @@ -76,8 +80,10 @@ static void DisplayXidCache(void); #define xc_by_recent_xmin_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) #define xc_by_child_xid_inc() ((void) 0) +#define xc_no_overflow_inc() ((void) 0) #define xc_slow_answer_inc() ((void) 0) #endif /* XIDCACHE_DEBUG */ @@ -302,7 +308,8 @@ ProcArrayClearTransaction(PGPROC *proc) /* * TransactionIdIsInProgress -- is given transaction running in some backend * - * There are three possibilities for finding a running transaction: + * Aside from some shortcuts such as checking RecentXmin and our own Xid, + * there are three possibilities for finding a running transaction: * * 1. the given Xid is a main transaction Id. We will find this out cheaply * by looking at the PGPROC struct for each backend. @@ -368,6 +375,18 @@ TransactionIdIsInProgress(TransactionId xid) LWLockAcquire(ProcArrayLock, LW_SHARED); + /* + * Now that we have the lock, we can check latestCompletedXid; if the + * target Xid is after that, it's surely still running. + */ + if (TransactionIdPrecedes(ShmemVariableCache->latestCompletedXid, xid)) + { + LWLockRelease(ProcArrayLock); + xc_by_latest_xid_inc(); + return true; + } + + /* No shortcuts, gotta grovel through the array */ for (i = 0; i < arrayP->numProcs; i++) { volatile PGPROC *proc = arrayP->procs[i]; @@ -434,7 +453,10 @@ TransactionIdIsInProgress(TransactionId xid) * running without looking at pg_subtrans. */ if (nxids == 0) + { + xc_no_overflow_inc(); return false; + } /* * Step 3: have to check pg_subtrans. @@ -451,8 +473,8 @@ TransactionIdIsInProgress(TransactionId xid) /* * It isn't aborted, so check whether the transaction tree it belongs to - * is still running (or, more precisely, whether it was running when this - * routine started -- note that we already released ProcArrayLock). + * is still running (or, more precisely, whether it was running when + * we held ProcArrayLock). */ topxid = SubTransGetTopmostTransaction(xid); Assert(TransactionIdIsValid(topxid)); @@ -1300,11 +1322,13 @@ static void DisplayXidCache(void) { fprintf(stderr, - "XidCache: xmin: %ld, myxact: %ld, mainxid: %ld, childxid: %ld, slow: %ld\n", + "XidCache: xmin: %ld, myxact: %ld, latest: %ld, mainxid: %ld, childxid: %ld, nooflo: %ld, slow: %ld\n", xc_by_recent_xmin, xc_by_my_xact, + xc_by_latest_xid, xc_by_main_xid, xc_by_child_xid, + xc_no_overflow, xc_slow_answer); }