aboutsummaryrefslogtreecommitdiff
path: root/src/backend/access/transam
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/access/transam')
-rw-r--r--src/backend/access/transam/clog.c8
-rw-r--r--src/backend/access/transam/commit_ts.c4
-rw-r--r--src/backend/access/transam/multixact.c20
-rw-r--r--src/backend/access/transam/subtrans.c8
-rw-r--r--src/backend/access/transam/twophase.c40
-rw-r--r--src/backend/access/transam/varsup.c76
-rw-r--r--src/backend/access/transam/xact.c35
-rw-r--r--src/backend/access/transam/xlog.c113
8 files changed, 121 insertions, 183 deletions
diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c
index aa089d83fa8..3bd55fbdd33 100644
--- a/src/backend/access/transam/clog.c
+++ b/src/backend/access/transam/clog.c
@@ -749,12 +749,12 @@ ZeroCLOGPage(int pageno, bool writeXlog)
/*
* This must be called ONCE during postmaster or standalone-backend startup,
- * after StartupXLOG has initialized ShmemVariableCache->nextXid.
+ * after StartupXLOG has initialized ShmemVariableCache->nextFullXid.
*/
void
StartupCLOG(void)
{
- TransactionId xid = ShmemVariableCache->nextXid;
+ TransactionId xid = XidFromFullTransactionId(ShmemVariableCache->nextFullXid);
int pageno = TransactionIdToPage(xid);
LWLockAcquire(CLogControlLock, LW_EXCLUSIVE);
@@ -773,7 +773,7 @@ StartupCLOG(void)
void
TrimCLOG(void)
{
- TransactionId xid = ShmemVariableCache->nextXid;
+ TransactionId xid = XidFromFullTransactionId(ShmemVariableCache->nextFullXid);
int pageno = TransactionIdToPage(xid);
LWLockAcquire(CLogControlLock, LW_EXCLUSIVE);
@@ -792,7 +792,7 @@ TrimCLOG(void)
* but makes no WAL entry). Let's just be safe. (We need not worry about
* pages beyond the current one, since those will be zeroed when first
* used. For the same reason, there is no need to do anything when
- * nextXid is exactly at a page boundary; and it's likely that the
+ * nextFullXid is exactly at a page boundary; and it's likely that the
* "current" page doesn't exist yet in that case.)
*/
if (TransactionIdToPgIndex(xid) != 0)
diff --git a/src/backend/access/transam/commit_ts.c b/src/backend/access/transam/commit_ts.c
index 9d7f15935dc..8162f884bd1 100644
--- a/src/backend/access/transam/commit_ts.c
+++ b/src/backend/access/transam/commit_ts.c
@@ -553,7 +553,7 @@ ZeroCommitTsPage(int pageno, bool writeXlog)
/*
* This must be called ONCE during postmaster or standalone-backend startup,
- * after StartupXLOG has initialized ShmemVariableCache->nextXid.
+ * after StartupXLOG has initialized ShmemVariableCache->nextFullXid.
*/
void
StartupCommitTs(void)
@@ -643,7 +643,7 @@ ActivateCommitTs(void)
}
LWLockRelease(CommitTsLock);
- xid = ShmemVariableCache->nextXid;
+ xid = XidFromFullTransactionId(ShmemVariableCache->nextFullXid);
pageno = TransactionIdToCTsPage(xid);
/*
diff --git a/src/backend/access/transam/multixact.c b/src/backend/access/transam/multixact.c
index c3998719405..763b9997071 100644
--- a/src/backend/access/transam/multixact.c
+++ b/src/backend/access/transam/multixact.c
@@ -3267,9 +3267,9 @@ multixact_redo(XLogReaderState *record)
xlrec->moff + xlrec->nmembers);
/*
- * Make sure nextXid is beyond any XID mentioned in the record. This
- * should be unnecessary, since any XID found here ought to have other
- * evidence in the XLOG, but let's be safe.
+ * Make sure nextFullXid is beyond any XID mentioned in the record.
+ * This should be unnecessary, since any XID found here ought to have
+ * other evidence in the XLOG, but let's be safe.
*/
max_xid = XLogRecGetXid(record);
for (i = 0; i < xlrec->nmembers; i++)
@@ -3278,19 +3278,7 @@ multixact_redo(XLogReaderState *record)
max_xid = xlrec->members[i].xid;
}
- /*
- * We don't expect anyone else to modify nextXid, hence startup
- * process doesn't need to hold a lock while checking this. We still
- * acquire the lock to modify it, though.
- */
- if (TransactionIdFollowsOrEquals(max_xid,
- ShmemVariableCache->nextXid))
- {
- LWLockAcquire(XidGenLock, LW_EXCLUSIVE);
- ShmemVariableCache->nextXid = max_xid;
- TransactionIdAdvance(ShmemVariableCache->nextXid);
- LWLockRelease(XidGenLock);
- }
+ AdvanceNextFullTransactionIdPastXid(max_xid);
}
else if (info == XLOG_MULTIXACT_TRUNCATE_ID)
{
diff --git a/src/backend/access/transam/subtrans.c b/src/backend/access/transam/subtrans.c
index cbc61294eb9..e667fd02385 100644
--- a/src/backend/access/transam/subtrans.c
+++ b/src/backend/access/transam/subtrans.c
@@ -241,14 +241,15 @@ ZeroSUBTRANSPage(int pageno)
/*
* This must be called ONCE during postmaster or standalone-backend startup,
- * after StartupXLOG has initialized ShmemVariableCache->nextXid.
+ * after StartupXLOG has initialized ShmemVariableCache->nextFullXid.
*
- * oldestActiveXID is the oldest XID of any prepared transaction, or nextXid
+ * oldestActiveXID is the oldest XID of any prepared transaction, or nextFullXid
* if there are none.
*/
void
StartupSUBTRANS(TransactionId oldestActiveXID)
{
+ FullTransactionId nextFullXid;
int startPage;
int endPage;
@@ -261,7 +262,8 @@ StartupSUBTRANS(TransactionId oldestActiveXID)
LWLockAcquire(SubtransControlLock, LW_EXCLUSIVE);
startPage = TransactionIdToPage(oldestActiveXID);
- endPage = TransactionIdToPage(ShmemVariableCache->nextXid);
+ nextFullXid = ShmemVariableCache->nextFullXid;
+ endPage = TransactionIdToPage(XidFromFullTransactionId(nextFullXid));
while (startPage != endPage)
{
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);
diff --git a/src/backend/access/transam/varsup.c b/src/backend/access/transam/varsup.c
index fe94fdaf049..efe18d3d3fb 100644
--- a/src/backend/access/transam/varsup.c
+++ b/src/backend/access/transam/varsup.c
@@ -73,7 +73,7 @@ GetNewTransactionId(bool isSubXact)
LWLockAcquire(XidGenLock, LW_EXCLUSIVE);
- xid = ShmemVariableCache->nextXid;
+ xid = XidFromFullTransactionId(ShmemVariableCache->nextFullXid);
/*----------
* Check to see if it's safe to assign another XID. This protects against
@@ -156,7 +156,7 @@ GetNewTransactionId(bool isSubXact)
/* Re-acquire lock and start over */
LWLockAcquire(XidGenLock, LW_EXCLUSIVE);
- xid = ShmemVariableCache->nextXid;
+ xid = XidFromFullTransactionId(ShmemVariableCache->nextFullXid);
}
/*
@@ -173,12 +173,12 @@ GetNewTransactionId(bool isSubXact)
ExtendSUBTRANS(xid);
/*
- * Now advance the nextXid counter. This must not happen until after we
- * have successfully completed ExtendCLOG() --- if that routine fails, we
- * want the next incoming transaction to try it again. We cannot assign
- * more XIDs until there is CLOG space for them.
+ * Now advance the nextFullXid counter. This must not happen until after
+ * we have successfully completed ExtendCLOG() --- if that routine fails,
+ * we want the next incoming transaction to try it again. We cannot
+ * assign more XIDs until there is CLOG space for them.
*/
- TransactionIdAdvance(ShmemVariableCache->nextXid);
+ FullTransactionIdAdvance(&ShmemVariableCache->nextFullXid);
/*
* We must store the new XID into the shared ProcArray before releasing
@@ -236,18 +236,64 @@ GetNewTransactionId(bool isSubXact)
}
/*
- * Read nextXid but don't allocate it.
+ * Read nextFullXid but don't allocate it.
*/
-TransactionId
-ReadNewTransactionId(void)
+FullTransactionId
+ReadNextFullTransactionId(void)
{
- TransactionId xid;
+ FullTransactionId fullXid;
LWLockAcquire(XidGenLock, LW_SHARED);
- xid = ShmemVariableCache->nextXid;
+ fullXid = ShmemVariableCache->nextFullXid;
LWLockRelease(XidGenLock);
- return xid;
+ return fullXid;
+}
+
+/*
+ * Advance nextFullXid to the value after a given xid. The epoch is inferred.
+ * This must only be called during recovery or from two-phase start-up code.
+ */
+void
+AdvanceNextFullTransactionIdPastXid(TransactionId xid)
+{
+ FullTransactionId newNextFullXid;
+ TransactionId next_xid;
+ uint32 epoch;
+
+ /*
+ * It is safe to read nextFullXid without a lock, because this is only
+ * called from the startup process or single-process mode, meaning that no
+ * other process can modify it.
+ */
+ Assert(AmStartupProcess() || !IsUnderPostmaster);
+
+ /* Fast return if this isn't an xid high enough to move the needle. */
+ next_xid = XidFromFullTransactionId(ShmemVariableCache->nextFullXid);
+ if (!TransactionIdFollowsOrEquals(xid, next_xid))
+ return;
+
+ /*
+ * Compute the FullTransactionId that comes after the given xid. To do
+ * this, we preserve the existing epoch, but detect when we've wrapped
+ * into a new epoch. This is necessary because WAL records and 2PC state
+ * currently contain 32 bit xids. The wrap logic is safe in those cases
+ * because the span of active xids cannot exceed one epoch at any given
+ * point in the WAL stream.
+ */
+ TransactionIdAdvance(xid);
+ epoch = EpochFromFullTransactionId(ShmemVariableCache->nextFullXid);
+ if (unlikely(xid < next_xid))
+ ++epoch;
+ newNextFullXid = FullTransactionIdFromEpochAndXid(epoch, xid);
+
+ /*
+ * We still need to take a lock to modify the value when there are
+ * concurrent readers.
+ */
+ LWLockAcquire(XidGenLock, LW_EXCLUSIVE);
+ ShmemVariableCache->nextFullXid = newNextFullXid;
+ LWLockRelease(XidGenLock);
}
/*
@@ -351,7 +397,7 @@ SetTransactionIdLimit(TransactionId oldest_datfrozenxid, Oid oldest_datoid)
ShmemVariableCache->xidStopLimit = xidStopLimit;
ShmemVariableCache->xidWrapLimit = xidWrapLimit;
ShmemVariableCache->oldestXidDB = oldest_datoid;
- curXid = ShmemVariableCache->nextXid;
+ curXid = XidFromFullTransactionId(ShmemVariableCache->nextFullXid);
LWLockRelease(XidGenLock);
/* Log the info */
@@ -427,7 +473,7 @@ ForceTransactionIdLimitUpdate(void)
/* Locking is probably not really necessary, but let's be careful */
LWLockAcquire(XidGenLock, LW_SHARED);
- nextXid = ShmemVariableCache->nextXid;
+ nextXid = XidFromFullTransactionId(ShmemVariableCache->nextFullXid);
xidVacLimit = ShmemVariableCache->xidVacLimit;
oldestXid = ShmemVariableCache->oldestXid;
oldestXidDB = ShmemVariableCache->oldestXidDB;
diff --git a/src/backend/access/transam/xact.c b/src/backend/access/transam/xact.c
index c3214d4f4d8..9b100050597 100644
--- a/src/backend/access/transam/xact.c
+++ b/src/backend/access/transam/xact.c
@@ -5636,21 +5636,8 @@ xact_redo_commit(xl_xact_parsed_commit *parsed,
max_xid = TransactionIdLatest(xid, parsed->nsubxacts, parsed->subxacts);
- /*
- * Make sure nextXid is beyond any XID mentioned in the record.
- *
- * We don't expect anyone else to modify nextXid, hence we don't need to
- * hold a lock while checking this. We still acquire the lock to modify
- * it, though.
- */
- if (TransactionIdFollowsOrEquals(max_xid,
- ShmemVariableCache->nextXid))
- {
- LWLockAcquire(XidGenLock, LW_EXCLUSIVE);
- ShmemVariableCache->nextXid = max_xid;
- TransactionIdAdvance(ShmemVariableCache->nextXid);
- LWLockRelease(XidGenLock);
- }
+ /* Make sure nextFullXid is beyond any XID mentioned in the record. */
+ AdvanceNextFullTransactionIdPastXid(max_xid);
Assert(((parsed->xinfo & XACT_XINFO_HAS_ORIGIN) == 0) ==
(origin_id == InvalidRepOriginId));
@@ -5792,25 +5779,11 @@ xact_redo_abort(xl_xact_parsed_abort *parsed, TransactionId xid)
Assert(TransactionIdIsValid(xid));
- /*
- * Make sure nextXid is beyond any XID mentioned in the record.
- *
- * We don't expect anyone else to modify nextXid, hence we don't need to
- * hold a lock while checking this. We still acquire the lock to modify
- * it, though.
- */
+ /* Make sure nextFullXid is beyond any XID mentioned in the record. */
max_xid = TransactionIdLatest(xid,
parsed->nsubxacts,
parsed->subxacts);
-
- if (TransactionIdFollowsOrEquals(max_xid,
- ShmemVariableCache->nextXid))
- {
- LWLockAcquire(XidGenLock, LW_EXCLUSIVE);
- ShmemVariableCache->nextXid = max_xid;
- TransactionIdAdvance(ShmemVariableCache->nextXid);
- LWLockRelease(XidGenLock);
- }
+ AdvanceNextFullTransactionIdPastXid(max_xid);
if (standbyState == STANDBY_DISABLED)
{
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ad12ebc4269..19d7911ec50 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -590,8 +590,7 @@ typedef struct XLogCtlData
/* Protected by info_lck: */
XLogwrtRqst LogwrtRqst;
XLogRecPtr RedoRecPtr; /* a recent copy of Insert->RedoRecPtr */
- uint32 ckptXidEpoch; /* nextXID & epoch of latest checkpoint */
- TransactionId ckptXid;
+ FullTransactionId ckptFullXid; /* nextFullXid of latest checkpoint */
XLogRecPtr asyncXactLSN; /* LSN of newest async commit/abort */
XLogRecPtr replicationSlotMinLSN; /* oldest LSN needed by any slot */
@@ -5115,8 +5114,8 @@ BootStrapXLOG(void)
checkPoint.ThisTimeLineID = ThisTimeLineID;
checkPoint.PrevTimeLineID = ThisTimeLineID;
checkPoint.fullPageWrites = fullPageWrites;
- checkPoint.nextXidEpoch = 0;
- checkPoint.nextXid = FirstNormalTransactionId;
+ checkPoint.nextFullXid =
+ FullTransactionIdFromEpochAndXid(0, FirstNormalTransactionId);
checkPoint.nextOid = FirstBootstrapObjectId;
checkPoint.nextMulti = FirstMultiXactId;
checkPoint.nextMultiOffset = 0;
@@ -5129,7 +5128,7 @@ BootStrapXLOG(void)
checkPoint.time = (pg_time_t) time(NULL);
checkPoint.oldestActiveXid = InvalidTransactionId;
- ShmemVariableCache->nextXid = checkPoint.nextXid;
+ ShmemVariableCache->nextFullXid = checkPoint.nextFullXid;
ShmemVariableCache->nextOid = checkPoint.nextOid;
ShmemVariableCache->oidCount = 0;
MultiXactSetNextMXact(checkPoint.nextMulti, checkPoint.nextMultiOffset);
@@ -6557,8 +6556,8 @@ StartupXLOG(void)
(uint32) (checkPoint.redo >> 32), (uint32) checkPoint.redo,
wasShutdown ? "true" : "false")));
ereport(DEBUG1,
- (errmsg_internal("next transaction ID: %u:%u; next OID: %u",
- checkPoint.nextXidEpoch, checkPoint.nextXid,
+ (errmsg_internal("next transaction ID: " UINT64_FORMAT "; next OID: %u",
+ U64FromFullTransactionId(checkPoint.nextFullXid),
checkPoint.nextOid)));
ereport(DEBUG1,
(errmsg_internal("next MultiXactId: %u; next MultiXactOffset: %u",
@@ -6573,12 +6572,12 @@ StartupXLOG(void)
(errmsg_internal("commit timestamp Xid oldest/newest: %u/%u",
checkPoint.oldestCommitTsXid,
checkPoint.newestCommitTsXid)));
- if (!TransactionIdIsNormal(checkPoint.nextXid))
+ if (!TransactionIdIsNormal(XidFromFullTransactionId(checkPoint.nextFullXid)))
ereport(PANIC,
(errmsg("invalid next transaction ID")));
/* initialize shared memory variables from the checkpoint record */
- ShmemVariableCache->nextXid = checkPoint.nextXid;
+ ShmemVariableCache->nextFullXid = checkPoint.nextFullXid;
ShmemVariableCache->nextOid = checkPoint.nextOid;
ShmemVariableCache->oidCount = 0;
MultiXactSetNextMXact(checkPoint.nextMulti, checkPoint.nextMultiOffset);
@@ -6587,8 +6586,7 @@ StartupXLOG(void)
SetMultiXactIdLimit(checkPoint.oldestMulti, checkPoint.oldestMultiDB, true);
SetCommitTsLimit(checkPoint.oldestCommitTsXid,
checkPoint.newestCommitTsXid);
- XLogCtl->ckptXidEpoch = checkPoint.nextXidEpoch;
- XLogCtl->ckptXid = checkPoint.nextXid;
+ XLogCtl->ckptFullXid = checkPoint.nextFullXid;
/*
* Initialize replication slots, before there's a chance to remove
@@ -6859,7 +6857,7 @@ StartupXLOG(void)
Assert(TransactionIdIsValid(oldestActiveXID));
/* Tell procarray about the range of xids it has to deal with */
- ProcArrayInitRecovery(ShmemVariableCache->nextXid);
+ ProcArrayInitRecovery(XidFromFullTransactionId(ShmemVariableCache->nextFullXid));
/*
* Startup commit log and subtrans only. MultiXact and commit
@@ -6889,9 +6887,9 @@ StartupXLOG(void)
running.xcnt = nxids;
running.subxcnt = 0;
running.subxid_overflow = false;
- running.nextXid = checkPoint.nextXid;
+ running.nextXid = XidFromFullTransactionId(checkPoint.nextFullXid);
running.oldestRunningXid = oldestActiveXID;
- latestCompletedXid = checkPoint.nextXid;
+ latestCompletedXid = XidFromFullTransactionId(checkPoint.nextFullXid);
TransactionIdRetreat(latestCompletedXid);
Assert(TransactionIdIsNormal(latestCompletedXid));
running.latestCompletedXid = latestCompletedXid;
@@ -7061,20 +7059,10 @@ StartupXLOG(void)
error_context_stack = &errcallback;
/*
- * ShmemVariableCache->nextXid must be beyond record's xid.
- *
- * 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.
+ * ShmemVariableCache->nextFullXid must be beyond record's
+ * xid.
*/
- if (TransactionIdFollowsOrEquals(record->xl_xid,
- ShmemVariableCache->nextXid))
- {
- LWLockAcquire(XidGenLock, LW_EXCLUSIVE);
- ShmemVariableCache->nextXid = record->xl_xid;
- TransactionIdAdvance(ShmemVariableCache->nextXid);
- LWLockRelease(XidGenLock);
- }
+ AdvanceNextFullTransactionIdPastXid(record->xl_xid);
/*
* Before replaying this record, check if this record causes
@@ -7654,7 +7642,7 @@ StartupXLOG(void)
/* also initialize latestCompletedXid, to nextXid - 1 */
LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
- ShmemVariableCache->latestCompletedXid = ShmemVariableCache->nextXid;
+ ShmemVariableCache->latestCompletedXid = XidFromFullTransactionId(ShmemVariableCache->nextFullXid);
TransactionIdRetreat(ShmemVariableCache->latestCompletedXid);
LWLockRelease(ProcArrayLock);
@@ -8248,41 +8236,6 @@ GetLastSegSwitchData(XLogRecPtr *lastSwitchLSN)
}
/*
- * GetNextXidAndEpoch - get the current nextXid value and associated epoch
- *
- * This is exported for use by code that would like to have 64-bit XIDs.
- * We don't really support such things, but all XIDs within the system
- * can be presumed "close to" the result, and thus the epoch associated
- * with them can be determined.
- */
-void
-GetNextXidAndEpoch(TransactionId *xid, uint32 *epoch)
-{
- uint32 ckptXidEpoch;
- TransactionId ckptXid;
- TransactionId nextXid;
-
- /* Must read checkpoint info first, else have race condition */
- SpinLockAcquire(&XLogCtl->info_lck);
- ckptXidEpoch = XLogCtl->ckptXidEpoch;
- ckptXid = XLogCtl->ckptXid;
- SpinLockRelease(&XLogCtl->info_lck);
-
- /* Now fetch current nextXid */
- nextXid = ReadNewTransactionId();
-
- /*
- * nextXid is certainly logically later than ckptXid. So if it's
- * numerically less, it must have wrapped into the next epoch.
- */
- if (nextXid < ckptXid)
- ckptXidEpoch++;
-
- *xid = nextXid;
- *epoch = ckptXidEpoch;
-}
-
-/*
* This must be called ONCE during postmaster or standalone-backend shutdown
*/
void
@@ -8701,7 +8654,7 @@ CreateCheckPoint(int flags)
* there.
*/
LWLockAcquire(XidGenLock, LW_SHARED);
- checkPoint.nextXid = ShmemVariableCache->nextXid;
+ checkPoint.nextFullXid = ShmemVariableCache->nextFullXid;
checkPoint.oldestXid = ShmemVariableCache->oldestXid;
checkPoint.oldestXidDB = ShmemVariableCache->oldestXidDB;
LWLockRelease(XidGenLock);
@@ -8711,11 +8664,6 @@ CreateCheckPoint(int flags)
checkPoint.newestCommitTsXid = ShmemVariableCache->newestCommitTsXid;
LWLockRelease(CommitTsLock);
- /* Increase XID epoch if we've wrapped around since last checkpoint */
- checkPoint.nextXidEpoch = ControlFile->checkPointCopy.nextXidEpoch;
- if (checkPoint.nextXid < ControlFile->checkPointCopy.nextXid)
- checkPoint.nextXidEpoch++;
-
LWLockAcquire(OidGenLock, LW_SHARED);
checkPoint.nextOid = ShmemVariableCache->nextOid;
if (!shutdown)
@@ -8859,8 +8807,7 @@ CreateCheckPoint(int flags)
/* Update shared-memory copy of checkpoint XID/epoch */
SpinLockAcquire(&XLogCtl->info_lck);
- XLogCtl->ckptXidEpoch = checkPoint.nextXidEpoch;
- XLogCtl->ckptXid = checkPoint.nextXid;
+ XLogCtl->ckptFullXid = checkPoint.nextFullXid;
SpinLockRelease(&XLogCtl->info_lck);
/*
@@ -9622,7 +9569,7 @@ xlog_redo(XLogReaderState *record)
memcpy(&checkPoint, XLogRecGetData(record), sizeof(CheckPoint));
/* In a SHUTDOWN checkpoint, believe the counters exactly */
LWLockAcquire(XidGenLock, LW_EXCLUSIVE);
- ShmemVariableCache->nextXid = checkPoint.nextXid;
+ ShmemVariableCache->nextFullXid = checkPoint.nextFullXid;
LWLockRelease(XidGenLock);
LWLockAcquire(OidGenLock, LW_EXCLUSIVE);
ShmemVariableCache->nextOid = checkPoint.nextOid;
@@ -9676,9 +9623,9 @@ xlog_redo(XLogReaderState *record)
running.xcnt = nxids;
running.subxcnt = 0;
running.subxid_overflow = false;
- running.nextXid = checkPoint.nextXid;
+ running.nextXid = XidFromFullTransactionId(checkPoint.nextFullXid);
running.oldestRunningXid = oldestActiveXID;
- latestCompletedXid = checkPoint.nextXid;
+ latestCompletedXid = XidFromFullTransactionId(checkPoint.nextFullXid);
TransactionIdRetreat(latestCompletedXid);
Assert(TransactionIdIsNormal(latestCompletedXid));
running.latestCompletedXid = latestCompletedXid;
@@ -9690,13 +9637,11 @@ xlog_redo(XLogReaderState *record)
}
/* ControlFile->checkPointCopy always tracks the latest ckpt XID */
- ControlFile->checkPointCopy.nextXidEpoch = checkPoint.nextXidEpoch;
- ControlFile->checkPointCopy.nextXid = checkPoint.nextXid;
+ ControlFile->checkPointCopy.nextFullXid = checkPoint.nextFullXid;
/* Update shared-memory copy of checkpoint XID/epoch */
SpinLockAcquire(&XLogCtl->info_lck);
- XLogCtl->ckptXidEpoch = checkPoint.nextXidEpoch;
- XLogCtl->ckptXid = checkPoint.nextXid;
+ XLogCtl->ckptFullXid = checkPoint.nextFullXid;
SpinLockRelease(&XLogCtl->info_lck);
/*
@@ -9717,9 +9662,9 @@ xlog_redo(XLogReaderState *record)
memcpy(&checkPoint, XLogRecGetData(record), sizeof(CheckPoint));
/* In an ONLINE checkpoint, treat the XID counter as a minimum */
LWLockAcquire(XidGenLock, LW_EXCLUSIVE);
- if (TransactionIdPrecedes(ShmemVariableCache->nextXid,
- checkPoint.nextXid))
- ShmemVariableCache->nextXid = checkPoint.nextXid;
+ if (FullTransactionIdPrecedes(ShmemVariableCache->nextFullXid,
+ checkPoint.nextFullXid))
+ ShmemVariableCache->nextFullXid = checkPoint.nextFullXid;
LWLockRelease(XidGenLock);
/*
@@ -9749,13 +9694,11 @@ xlog_redo(XLogReaderState *record)
SetTransactionIdLimit(checkPoint.oldestXid,
checkPoint.oldestXidDB);
/* ControlFile->checkPointCopy always tracks the latest ckpt XID */
- ControlFile->checkPointCopy.nextXidEpoch = checkPoint.nextXidEpoch;
- ControlFile->checkPointCopy.nextXid = checkPoint.nextXid;
+ ControlFile->checkPointCopy.nextFullXid = checkPoint.nextFullXid;
/* Update shared-memory copy of checkpoint XID/epoch */
SpinLockAcquire(&XLogCtl->info_lck);
- XLogCtl->ckptXidEpoch = checkPoint.nextXidEpoch;
- XLogCtl->ckptXid = checkPoint.nextXid;
+ XLogCtl->ckptFullXid = checkPoint.nextFullXid;
SpinLockRelease(&XLogCtl->info_lck);
/* TLI should not change in an on-line checkpoint */