Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 611b439

Browse files
committed
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.
1 parent ba8a9a9 commit 611b439

File tree

3 files changed

+67
-32
lines changed

3 files changed

+67
-32
lines changed

src/backend/access/transam/transam.c

+48-29
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
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
@@ -25,12 +25,11 @@
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
*/
3534
static TransactionId cachedFetchXid = InvalidTransactionId;
3635
static XidStatus cachedFetchXidStatus;
@@ -39,9 +38,14 @@ static XLogRecPtr cachedCommitLSN;
3938
/* Handy constant for an invalid xlog recptr */
4039
static 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)
8286
xidstatus = 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
*/
8892
if (xidstatus != TRANSACTION_STATUS_IN_PROGRESS &&
8993
xidstatus != TRANSACTION_STATUS_SUB_COMMITTED)
@@ -96,12 +100,11 @@ TransactionLogFetch(TransactionId transactionId)
96100
return 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
*/
106109
static inline void
107110
TransactionLogUpdate(TransactionId transactionId,
@@ -131,32 +134,27 @@ TransactionLogMultiUpdate(int nxids, TransactionId *xids,
131134
TransactionIdSetStatus(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)
262260
return 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)
292312
TransactionLogUpdate(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)
352371
lsn);
353372
}
354373

355-
356374
/*
357375
* TransactionIdAbortTree
358376
* Marks all the given transaction ids as aborted.
@@ -368,6 +386,7 @@ TransactionIdAbortTree(int nxids, TransactionId *xids)
368386
InvalidXLogRecPtr);
369387
}
370388

389+
371390
/*
372391
* TransactionIdPrecedes --- is id1 logically < id2?
373392
*/

src/backend/storage/ipc/procarray.c

+17-2
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
*
2424
*
2525
* IDENTIFICATION
26-
* $PostgreSQL: pgsql/src/backend/storage/ipc/procarray.c,v 1.40 2008/01/09 21:52:36 tgl Exp $
26+
* $PostgreSQL: pgsql/src/backend/storage/ipc/procarray.c,v 1.41 2008/03/11 20:20:35 tgl Exp $
2727
*
2828
*-------------------------------------------------------------------------
2929
*/
@@ -60,6 +60,7 @@ static ProcArrayStruct *procArray;
6060

6161
/* counters for XidCache measurement */
6262
static long xc_by_recent_xmin = 0;
63+
static long xc_by_known_xact = 0;
6364
static long xc_by_my_xact = 0;
6465
static long xc_by_latest_xid = 0;
6566
static long xc_by_main_xid = 0;
@@ -68,6 +69,7 @@ static long xc_no_overflow = 0;
6869
static long xc_slow_answer = 0;
6970

7071
#define xc_by_recent_xmin_inc() (xc_by_recent_xmin++)
72+
#define xc_by_known_xact_inc() (xc_by_known_xact++)
7173
#define xc_by_my_xact_inc() (xc_by_my_xact++)
7274
#define xc_by_latest_xid_inc() (xc_by_latest_xid++)
7375
#define xc_by_main_xid_inc() (xc_by_main_xid++)
@@ -79,6 +81,7 @@ static void DisplayXidCache(void);
7981
#else /* !XIDCACHE_DEBUG */
8082

8183
#define xc_by_recent_xmin_inc() ((void) 0)
84+
#define xc_by_known_xact_inc() ((void) 0)
8285
#define xc_by_my_xact_inc() ((void) 0)
8386
#define xc_by_latest_xid_inc() ((void) 0)
8487
#define xc_by_main_xid_inc() ((void) 0)
@@ -353,6 +356,17 @@ TransactionIdIsInProgress(TransactionId xid)
353356
return false;
354357
}
355358

359+
/*
360+
* We may have just checked the status of this transaction, so if it is
361+
* already known to be completed, we can fall out without any access to
362+
* shared memory.
363+
*/
364+
if (TransactionIdIsKnownCompleted(xid))
365+
{
366+
xc_by_known_xact_inc();
367+
return false;
368+
}
369+
356370
/*
357371
* Also, we can handle our own transaction (and subtransactions) without
358372
* any access to shared memory.
@@ -1335,8 +1349,9 @@ static void
13351349
DisplayXidCache(void)
13361350
{
13371351
fprintf(stderr,
1338-
"XidCache: xmin: %ld, myxact: %ld, latest: %ld, mainxid: %ld, childxid: %ld, nooflo: %ld, slow: %ld\n",
1352+
"XidCache: xmin: %ld, known: %ld, myxact: %ld, latest: %ld, mainxid: %ld, childxid: %ld, nooflo: %ld, slow: %ld\n",
13391353
xc_by_recent_xmin,
1354+
xc_by_known_xact,
13401355
xc_by_my_xact,
13411356
xc_by_latest_xid,
13421357
xc_by_main_xid,

src/include/access/transam.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $PostgreSQL: pgsql/src/include/access/transam.h,v 1.64 2008/01/01 19:45:56 momjian Exp $
10+
* $PostgreSQL: pgsql/src/include/access/transam.h,v 1.65 2008/03/11 20:20:35 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -138,6 +138,7 @@ extern VariableCache ShmemVariableCache;
138138
*/
139139
extern bool TransactionIdDidCommit(TransactionId transactionId);
140140
extern bool TransactionIdDidAbort(TransactionId transactionId);
141+
extern bool TransactionIdIsKnownCompleted(TransactionId transactionId);
141142
extern void TransactionIdCommit(TransactionId transactionId);
142143
extern void TransactionIdAsyncCommit(TransactionId transactionId, XLogRecPtr lsn);
143144
extern void TransactionIdAbort(TransactionId transactionId);

0 commit comments

Comments
 (0)