diff options
Diffstat (limited to 'src/backend/access/transam')
-rw-r--r-- | src/backend/access/transam/clog.c | 8 | ||||
-rw-r--r-- | src/backend/access/transam/commit_ts.c | 4 | ||||
-rw-r--r-- | src/backend/access/transam/multixact.c | 20 | ||||
-rw-r--r-- | src/backend/access/transam/subtrans.c | 8 | ||||
-rw-r--r-- | src/backend/access/transam/twophase.c | 40 | ||||
-rw-r--r-- | src/backend/access/transam/varsup.c | 76 | ||||
-rw-r--r-- | src/backend/access/transam/xact.c | 35 | ||||
-rw-r--r-- | src/backend/access/transam/xlog.c | 113 |
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 */ |