mirror of
https://github.com/postgres/postgres.git
synced 2025-07-15 19:21:59 +03:00
Make TransactionIdIsInProgress check transam.c's single-item XID status cache
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.
This commit is contained in:
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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
|
* NOTES
|
||||||
* This file contains the high level access-method interface to the
|
* This file contains the high level access-method interface to the
|
||||||
@ -25,12 +25,11 @@
|
|||||||
#include "utils/tqual.h"
|
#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 TransactionId cachedFetchXid = InvalidTransactionId;
|
||||||
static XidStatus cachedFetchXidStatus;
|
static XidStatus cachedFetchXidStatus;
|
||||||
@ -39,9 +38,14 @@ static XLogRecPtr cachedCommitLSN;
|
|||||||
/* Handy constant for an invalid xlog recptr */
|
/* Handy constant for an invalid xlog recptr */
|
||||||
static const XLogRecPtr InvalidXLogRecPtr = {0, 0};
|
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
|
* TransactionLogFetch
|
||||||
* TransactionLogUpdate
|
* TransactionLogUpdate
|
||||||
@ -82,8 +86,8 @@ TransactionLogFetch(TransactionId transactionId)
|
|||||||
xidstatus = TransactionIdGetStatus(transactionId, &xidlsn);
|
xidstatus = TransactionIdGetStatus(transactionId, &xidlsn);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* DO NOT cache status for unfinished or sub-committed transactions! We
|
* Cache it, but DO NOT cache status for unfinished or sub-committed
|
||||||
* only cache status that is guaranteed not to change.
|
* transactions! We only cache status that is guaranteed not to change.
|
||||||
*/
|
*/
|
||||||
if (xidstatus != TRANSACTION_STATUS_IN_PROGRESS &&
|
if (xidstatus != TRANSACTION_STATUS_IN_PROGRESS &&
|
||||||
xidstatus != TRANSACTION_STATUS_SUB_COMMITTED)
|
xidstatus != TRANSACTION_STATUS_SUB_COMMITTED)
|
||||||
@ -96,12 +100,11 @@ TransactionLogFetch(TransactionId transactionId)
|
|||||||
return xidstatus;
|
return xidstatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --------------------------------
|
/*
|
||||||
* TransactionLogUpdate
|
* TransactionLogUpdate
|
||||||
*
|
*
|
||||||
* Store the new status of a transaction. The commit record LSN must be
|
* Store the new status of a transaction. The commit record LSN must be
|
||||||
* passed when recording an async commit; else it should be InvalidXLogRecPtr.
|
* passed when recording an async commit; else it should be InvalidXLogRecPtr.
|
||||||
* --------------------------------
|
|
||||||
*/
|
*/
|
||||||
static inline void
|
static inline void
|
||||||
TransactionLogUpdate(TransactionId transactionId,
|
TransactionLogUpdate(TransactionId transactionId,
|
||||||
@ -131,32 +134,27 @@ TransactionLogMultiUpdate(int nxids, TransactionId *xids,
|
|||||||
TransactionIdSetStatus(xids[i], status, lsn);
|
TransactionIdSetStatus(xids[i], status, lsn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* ----------------------------------------------------------------
|
/* ----------------------------------------------------------------
|
||||||
* Interface functions
|
* Interface functions
|
||||||
*
|
*
|
||||||
* TransactionId DidCommit
|
* TransactionIdDidCommit
|
||||||
* TransactionId DidAbort
|
* TransactionIdDidAbort
|
||||||
* TransactionId IsInProgress
|
|
||||||
* ========
|
* ========
|
||||||
* these functions test the transaction status of
|
* these functions test the transaction status of
|
||||||
* a specified transaction id.
|
* a specified transaction id.
|
||||||
*
|
*
|
||||||
* TransactionId Commit
|
* TransactionIdCommit
|
||||||
* TransactionId Abort
|
* TransactionIdAbort
|
||||||
* ========
|
* ========
|
||||||
* these functions set the transaction status
|
* these functions set the transaction status
|
||||||
* of the specified xid.
|
* 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
|
* TransactionIdDidCommit
|
||||||
* True iff transaction associated with the identifier did commit.
|
* True iff transaction associated with the identifier did commit.
|
||||||
@ -262,11 +260,33 @@ TransactionIdDidAbort(TransactionId transactionId)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --------------------------------
|
/*
|
||||||
* TransactionId Commit
|
* TransactionIdIsKnownCompleted
|
||||||
* TransactionId Abort
|
* 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
|
* TransactionIdCommit
|
||||||
@ -292,7 +312,6 @@ TransactionIdAsyncCommit(TransactionId transactionId, XLogRecPtr lsn)
|
|||||||
TransactionLogUpdate(transactionId, TRANSACTION_STATUS_COMMITTED, lsn);
|
TransactionLogUpdate(transactionId, TRANSACTION_STATUS_COMMITTED, lsn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* TransactionIdAbort
|
* TransactionIdAbort
|
||||||
* Aborts the transaction associated with the identifier.
|
* Aborts the transaction associated with the identifier.
|
||||||
@ -352,7 +371,6 @@ TransactionIdAsyncCommitTree(int nxids, TransactionId *xids, XLogRecPtr lsn)
|
|||||||
lsn);
|
lsn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* TransactionIdAbortTree
|
* TransactionIdAbortTree
|
||||||
* Marks all the given transaction ids as aborted.
|
* Marks all the given transaction ids as aborted.
|
||||||
@ -368,6 +386,7 @@ TransactionIdAbortTree(int nxids, TransactionId *xids)
|
|||||||
InvalidXLogRecPtr);
|
InvalidXLogRecPtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* TransactionIdPrecedes --- is id1 logically < id2?
|
* TransactionIdPrecedes --- is id1 logically < id2?
|
||||||
*/
|
*/
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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 */
|
/* counters for XidCache measurement */
|
||||||
static long xc_by_recent_xmin = 0;
|
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_my_xact = 0;
|
||||||
static long xc_by_latest_xid = 0;
|
static long xc_by_latest_xid = 0;
|
||||||
static long xc_by_main_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;
|
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_known_xact_inc() (xc_by_known_xact++)
|
||||||
#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_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++)
|
||||||
@ -79,6 +81,7 @@ static void DisplayXidCache(void);
|
|||||||
#else /* !XIDCACHE_DEBUG */
|
#else /* !XIDCACHE_DEBUG */
|
||||||
|
|
||||||
#define xc_by_recent_xmin_inc() ((void) 0)
|
#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_my_xact_inc() ((void) 0)
|
||||||
#define xc_by_latest_xid_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)
|
||||||
@ -353,6 +356,17 @@ TransactionIdIsInProgress(TransactionId xid)
|
|||||||
return false;
|
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
|
* Also, we can handle our own transaction (and subtransactions) without
|
||||||
* any access to shared memory.
|
* any access to shared memory.
|
||||||
@ -1335,8 +1349,9 @@ static void
|
|||||||
DisplayXidCache(void)
|
DisplayXidCache(void)
|
||||||
{
|
{
|
||||||
fprintf(stderr,
|
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_recent_xmin,
|
||||||
|
xc_by_known_xact,
|
||||||
xc_by_my_xact,
|
xc_by_my_xact,
|
||||||
xc_by_latest_xid,
|
xc_by_latest_xid,
|
||||||
xc_by_main_xid,
|
xc_by_main_xid,
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* 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 TransactionIdDidCommit(TransactionId transactionId);
|
||||||
extern bool TransactionIdDidAbort(TransactionId transactionId);
|
extern bool TransactionIdDidAbort(TransactionId transactionId);
|
||||||
|
extern bool TransactionIdIsKnownCompleted(TransactionId transactionId);
|
||||||
extern void TransactionIdCommit(TransactionId transactionId);
|
extern void TransactionIdCommit(TransactionId transactionId);
|
||||||
extern void TransactionIdAsyncCommit(TransactionId transactionId, XLogRecPtr lsn);
|
extern void TransactionIdAsyncCommit(TransactionId transactionId, XLogRecPtr lsn);
|
||||||
extern void TransactionIdAbort(TransactionId transactionId);
|
extern void TransactionIdAbort(TransactionId transactionId);
|
||||||
|
Reference in New Issue
Block a user