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

Lines changed: 48 additions & 29 deletions
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

Lines changed: 17 additions & 2 deletions
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

Lines changed: 2 additions & 1 deletion
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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy