diff options
Diffstat (limited to 'src/backend/access/transam/xlog.c')
-rw-r--r-- | src/backend/access/transam/xlog.c | 49 |
1 files changed, 36 insertions, 13 deletions
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index b128bfda36d..5e59c1ab196 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -6625,12 +6625,20 @@ StartupXLOG(void) errcontext.previous = error_context_stack; error_context_stack = &errcontext; - /* nextXid must be beyond record's xid */ + /* + * 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. + */ if (TransactionIdFollowsOrEquals(record->xl_xid, ShmemVariableCache->nextXid)) { + LWLockAcquire(XidGenLock, LW_EXCLUSIVE); ShmemVariableCache->nextXid = record->xl_xid; TransactionIdAdvance(ShmemVariableCache->nextXid); + LWLockRelease(XidGenLock); } /* @@ -6656,6 +6664,7 @@ StartupXLOG(void) TransactionIdIsValid(record->xl_xid)) RecordKnownAssignedTransactionIds(record->xl_xid); + /* Now apply the WAL record itself */ RmgrTable[record->xl_rmid].rm_redo(EndRecPtr, record); /* Pop the error context stack */ @@ -6971,8 +6980,10 @@ StartupXLOG(void) XLogCtl->ckptXid = ControlFile->checkPointCopy.nextXid; /* also initialize latestCompletedXid, to nextXid - 1 */ + LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE); ShmemVariableCache->latestCompletedXid = ShmemVariableCache->nextXid; TransactionIdRetreat(ShmemVariableCache->latestCompletedXid); + LWLockRelease(ProcArrayLock); /* * Start up the commit log and subtrans, if not already done for @@ -8547,12 +8558,18 @@ xlog_redo(XLogRecPtr lsn, XLogRecord *record) { Oid nextOid; + /* + * We used to try to take the maximum of ShmemVariableCache->nextOid + * and the recorded nextOid, but that fails if the OID counter wraps + * around. Since no OID allocation should be happening during replay + * anyway, better to just believe the record exactly. We still take + * OidGenLock while setting the variable, just in case. + */ memcpy(&nextOid, XLogRecGetData(record), sizeof(Oid)); - if (ShmemVariableCache->nextOid < nextOid) - { - ShmemVariableCache->nextOid = nextOid; - ShmemVariableCache->oidCount = 0; - } + LWLockAcquire(OidGenLock, LW_EXCLUSIVE); + ShmemVariableCache->nextOid = nextOid; + ShmemVariableCache->oidCount = 0; + LWLockRelease(OidGenLock); } else if (info == XLOG_CHECKPOINT_SHUTDOWN) { @@ -8560,9 +8577,13 @@ xlog_redo(XLogRecPtr lsn, XLogRecord *record) memcpy(&checkPoint, XLogRecGetData(record), sizeof(CheckPoint)); /* In a SHUTDOWN checkpoint, believe the counters exactly */ + LWLockAcquire(XidGenLock, LW_EXCLUSIVE); ShmemVariableCache->nextXid = checkPoint.nextXid; + LWLockRelease(XidGenLock); + LWLockAcquire(OidGenLock, LW_EXCLUSIVE); ShmemVariableCache->nextOid = checkPoint.nextOid; ShmemVariableCache->oidCount = 0; + LWLockRelease(OidGenLock); MultiXactSetNextMXact(checkPoint.nextMulti, checkPoint.nextMultiOffset); SetTransactionIdLimit(checkPoint.oldestXid, checkPoint.oldestXidDB); @@ -8575,7 +8596,7 @@ xlog_redo(XLogRecPtr lsn, XLogRecord *record) if (InArchiveRecovery && !XLogRecPtrIsInvalid(ControlFile->backupStartPoint) && XLogRecPtrIsInvalid(ControlFile->backupEndPoint)) - ereport(ERROR, + ereport(PANIC, (errmsg("online backup was canceled, recovery cannot continue"))); /* @@ -8641,15 +8662,17 @@ xlog_redo(XLogRecPtr lsn, XLogRecord *record) CheckPoint checkPoint; memcpy(&checkPoint, XLogRecGetData(record), sizeof(CheckPoint)); - /* In an ONLINE checkpoint, treat the counters like NEXTOID */ + /* 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 (ShmemVariableCache->nextOid < checkPoint.nextOid) - { - ShmemVariableCache->nextOid = checkPoint.nextOid; - ShmemVariableCache->oidCount = 0; - } + LWLockRelease(XidGenLock); + /* ... but still treat OID counter as exact */ + LWLockAcquire(OidGenLock, LW_EXCLUSIVE); + ShmemVariableCache->nextOid = checkPoint.nextOid; + ShmemVariableCache->oidCount = 0; + LWLockRelease(OidGenLock); MultiXactAdvanceNextMXact(checkPoint.nextMulti, checkPoint.nextMultiOffset); if (TransactionIdPrecedes(ShmemVariableCache->oldestXid, |