aboutsummaryrefslogtreecommitdiff
path: root/src/backend/access/transam/twophase.c
diff options
context:
space:
mode:
authorThomas Munro <tmunro@postgresql.org>2019-03-28 10:34:43 +1300
committerThomas Munro <tmunro@postgresql.org>2019-03-28 18:12:20 +1300
commit2fc7af5e966043a412e8e69c135fae55a2db6d4f (patch)
treeed1c75e994fe6a49e1636ab5180b608a5dfcc423 /src/backend/access/transam/twophase.c
parent2a96909a4a8c38705163b83a81b228d5aec197f9 (diff)
downloadpostgresql-2fc7af5e966043a412e8e69c135fae55a2db6d4f.tar.gz
postgresql-2fc7af5e966043a412e8e69c135fae55a2db6d4f.zip
Add basic infrastructure for 64 bit transaction IDs.
Instead of inferring epoch progress from xids and checkpoints, introduce a 64 bit FullTransactionId type and use it to track xid generation. This fixes an unlikely bug where the epoch is reported incorrectly if the range of active xids wraps around more than once between checkpoints. The only user-visible effect of this commit is to correct the epoch used by txid_current() and txid_status(), also visible with pg_controldata, in those rare circumstances. It also creates some basic infrastructure so that later patches can use 64 bit transaction IDs in more places. The new type is a struct that we pass by value, as a form of strong typedef. This prevents the sort of accidental confusion between TransactionId and FullTransactionId that would be possible if we were to use a plain old uint64. Author: Thomas Munro Reported-by: Amit Kapila Reviewed-by: Andres Freund, Tom Lane, Heikki Linnakangas Discussion: https://postgr.es/m/CAA4eK1%2BMv%2Bmb0HFfWM9Srtc6MVe160WFurXV68iAFMcagRZ0dQ%40mail.gmail.com
Diffstat (limited to 'src/backend/access/transam/twophase.c')
-rw-r--r--src/backend/access/transam/twophase.c40
1 files changed, 13 insertions, 27 deletions
diff --git a/src/backend/access/transam/twophase.c b/src/backend/access/transam/twophase.c
index 21986e48fe2..11992f7447d 100644
--- a/src/backend/access/transam/twophase.c
+++ b/src/backend/access/transam/twophase.c
@@ -1878,16 +1878,16 @@ restoreTwoPhaseData(void)
*
* Scan the shared memory entries of TwoPhaseState and determine the range
* of valid XIDs present. This is run during database startup, after we
- * have completed reading WAL. ShmemVariableCache->nextXid has been set to
+ * have completed reading WAL. ShmemVariableCache->nextFullXid has been set to
* one more than the highest XID for which evidence exists in WAL.
*
- * We throw away any prepared xacts with main XID beyond nextXid --- if any
+ * We throw away any prepared xacts with main XID beyond nextFullXid --- if any
* are present, it suggests that the DBA has done a PITR recovery to an
* earlier point in time without cleaning out pg_twophase. We dare not
* try to recover such prepared xacts since they likely depend on database
* state that doesn't exist now.
*
- * However, we will advance nextXid beyond any subxact XIDs belonging to
+ * However, we will advance nextFullXid beyond any subxact XIDs belonging to
* valid prepared xacts. We need to do this since subxact commit doesn't
* write a WAL entry, and so there might be no evidence in WAL of those
* subxact XIDs.
@@ -1897,7 +1897,7 @@ restoreTwoPhaseData(void)
* backup should be rolled in.
*
* Our other responsibility is to determine and return the oldest valid XID
- * among the prepared xacts (if none, return ShmemVariableCache->nextXid).
+ * among the prepared xacts (if none, return ShmemVariableCache->nextFullXid).
* This is needed to synchronize pg_subtrans startup properly.
*
* If xids_p and nxids_p are not NULL, pointer to a palloc'd array of all
@@ -1907,7 +1907,8 @@ restoreTwoPhaseData(void)
TransactionId
PrescanPreparedTransactions(TransactionId **xids_p, int *nxids_p)
{
- TransactionId origNextXid = ShmemVariableCache->nextXid;
+ FullTransactionId nextFullXid = ShmemVariableCache->nextFullXid;
+ TransactionId origNextXid = XidFromFullTransactionId(nextFullXid);
TransactionId result = origNextXid;
TransactionId *xids = NULL;
int nxids = 0;
@@ -2123,7 +2124,7 @@ RecoverPreparedTransactions(void)
*
* If setParent is true, set up subtransaction parent linkages.
*
- * If setNextXid is true, set ShmemVariableCache->nextXid to the newest
+ * If setNextXid is true, set ShmemVariableCache->nextFullXid to the newest
* value scanned.
*/
static char *
@@ -2132,7 +2133,8 @@ ProcessTwoPhaseBuffer(TransactionId xid,
bool fromdisk,
bool setParent, bool setNextXid)
{
- TransactionId origNextXid = ShmemVariableCache->nextXid;
+ FullTransactionId nextFullXid = ShmemVariableCache->nextFullXid;
+ TransactionId origNextXid = XidFromFullTransactionId(nextFullXid);
TransactionId *subxids;
char *buf;
TwoPhaseFileHeader *hdr;
@@ -2212,7 +2214,7 @@ ProcessTwoPhaseBuffer(TransactionId xid,
/*
* Examine subtransaction XIDs ... they should all follow main XID, and
- * they may force us to advance nextXid.
+ * they may force us to advance nextFullXid.
*/
subxids = (TransactionId *) (buf +
MAXALIGN(sizeof(TwoPhaseFileHeader)) +
@@ -2223,25 +2225,9 @@ ProcessTwoPhaseBuffer(TransactionId xid,
Assert(TransactionIdFollows(subxid, xid));
- /* update nextXid if needed */
- if (setNextXid &&
- TransactionIdFollowsOrEquals(subxid,
- ShmemVariableCache->nextXid))
- {
- /*
- * We don't expect anyone else to modify nextXid, hence we don't
- * need to hold a lock while examining it. We still acquire the
- * lock to modify it, though, so we recheck.
- */
- LWLockAcquire(XidGenLock, LW_EXCLUSIVE);
- if (TransactionIdFollowsOrEquals(subxid,
- ShmemVariableCache->nextXid))
- {
- ShmemVariableCache->nextXid = subxid;
- TransactionIdAdvance(ShmemVariableCache->nextXid);
- }
- LWLockRelease(XidGenLock);
- }
+ /* update nextFullXid if needed */
+ if (setNextXid)
+ AdvanceNextFullTransactionIdPastXid(subxid);
if (setParent)
SubTransSetParent(subxid, xid);