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.
This commit is contained in:
Tom Lane 2007-09-23 18:50:38 +00:00
parent d16f270e59
commit 1b3d400cac
1 changed files with 29 additions and 5 deletions

View File

@ -23,7 +23,7 @@
* *
* *
* IDENTIFICATION * 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 */ /* counters for XidCache measurement */
static long xc_by_recent_xmin = 0; static long xc_by_recent_xmin = 0;
static long xc_by_my_xact = 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_main_xid = 0;
static long xc_by_child_xid = 0; static long xc_by_child_xid = 0;
static long xc_no_overflow = 0;
static long xc_slow_answer = 0; static long xc_slow_answer = 0;
#define xc_by_recent_xmin_inc() (xc_by_recent_xmin++) #define xc_by_recent_xmin_inc() (xc_by_recent_xmin++)
#define xc_by_my_xact_inc() (xc_by_my_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++) #define xc_by_main_xid_inc() (xc_by_main_xid++)
#define xc_by_child_xid_inc() (xc_by_child_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++) #define xc_slow_answer_inc() (xc_slow_answer++)
static void DisplayXidCache(void); static void DisplayXidCache(void);
@ -76,8 +80,10 @@ static void DisplayXidCache(void);
#define xc_by_recent_xmin_inc() ((void) 0) #define xc_by_recent_xmin_inc() ((void) 0)
#define xc_by_my_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) #define xc_by_main_xid_inc() ((void) 0)
#define xc_by_child_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) #define xc_slow_answer_inc() ((void) 0)
#endif /* XIDCACHE_DEBUG */ #endif /* XIDCACHE_DEBUG */
@ -302,7 +308,8 @@ ProcArrayClearTransaction(PGPROC *proc)
/* /*
* TransactionIdIsInProgress -- is given transaction running in some backend * 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 * 1. the given Xid is a main transaction Id. We will find this out cheaply
* by looking at the PGPROC struct for each backend. * by looking at the PGPROC struct for each backend.
@ -368,6 +375,18 @@ TransactionIdIsInProgress(TransactionId xid)
LWLockAcquire(ProcArrayLock, LW_SHARED); 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++) for (i = 0; i < arrayP->numProcs; i++)
{ {
volatile PGPROC *proc = arrayP->procs[i]; volatile PGPROC *proc = arrayP->procs[i];
@ -434,7 +453,10 @@ TransactionIdIsInProgress(TransactionId xid)
* running without looking at pg_subtrans. * running without looking at pg_subtrans.
*/ */
if (nxids == 0) if (nxids == 0)
{
xc_no_overflow_inc();
return false; return false;
}
/* /*
* Step 3: have to check pg_subtrans. * 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 * 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 * is still running (or, more precisely, whether it was running when
* routine started -- note that we already released ProcArrayLock). * we held ProcArrayLock).
*/ */
topxid = SubTransGetTopmostTransaction(xid); topxid = SubTransGetTopmostTransaction(xid);
Assert(TransactionIdIsValid(topxid)); Assert(TransactionIdIsValid(topxid));
@ -1300,11 +1322,13 @@ static void
DisplayXidCache(void) DisplayXidCache(void)
{ {
fprintf(stderr, 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_recent_xmin,
xc_by_my_xact, xc_by_my_xact,
xc_by_latest_xid,
xc_by_main_xid, xc_by_main_xid,
xc_by_child_xid, xc_by_child_xid,
xc_no_overflow,
xc_slow_answer); xc_slow_answer);
} }