Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit f1b8a84

Browse files
committed
Avoid problems with OID wraparound during WAL replay.
Fix a longstanding thinko in replay of NEXTOID and checkpoint records: we tried to advance nextOid only if it was behind the value in the WAL record, but the comparison would draw the wrong conclusion if OID wraparound had occurred since the previous value. Better to just unconditionally assign the new value, since OID assignment shouldn't be happening during replay anyway. The consequences of a failure to update nextOid would be pretty minimal, since we have long had the code set up to obtain another OID and try again if the generated value is already in use. But in the worst case there could be significant performance glitches while such loops iterate through many already-used OIDs before finding a free one. The odds of a wraparound happening during WAL replay would be small in a crash-recovery scenario, and the length of any ensuing OID-assignment stall quite limited anyway. But neither of these statements hold true for a replication slave that follows a WAL stream for a long period; its behavior upon going live could be almost unboundedly bad. Hence it seems worth back-patching this fix into all supported branches. Already fixed in HEAD in commit c6d76d7.
1 parent 2a84671 commit f1b8a84

File tree

1 file changed

+12
-11
lines changed
  • src/backend/access/transam

1 file changed

+12
-11
lines changed

src/backend/access/transam/xlog.c

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8387,12 +8387,15 @@ xlog_redo(XLogRecPtr lsn, XLogRecord *record)
83878387
{
83888388
Oid nextOid;
83898389

8390+
/*
8391+
* We used to try to take the maximum of ShmemVariableCache->nextOid
8392+
* and the recorded nextOid, but that fails if the OID counter wraps
8393+
* around. Since no OID allocation should be happening during replay
8394+
* anyway, better to just believe the record exactly.
8395+
*/
83908396
memcpy(&nextOid, XLogRecGetData(record), sizeof(Oid));
8391-
if (ShmemVariableCache->nextOid < nextOid)
8392-
{
8393-
ShmemVariableCache->nextOid = nextOid;
8394-
ShmemVariableCache->oidCount = 0;
8395-
}
8397+
ShmemVariableCache->nextOid = nextOid;
8398+
ShmemVariableCache->oidCount = 0;
83968399
}
83978400
else if (info == XLOG_CHECKPOINT_SHUTDOWN)
83988401
{
@@ -8480,15 +8483,13 @@ xlog_redo(XLogRecPtr lsn, XLogRecord *record)
84808483
CheckPoint checkPoint;
84818484

84828485
memcpy(&checkPoint, XLogRecGetData(record), sizeof(CheckPoint));
8483-
/* In an ONLINE checkpoint, treat the counters like NEXTOID */
8486+
/* In an ONLINE checkpoint, treat the XID counter as a minimum */
84848487
if (TransactionIdPrecedes(ShmemVariableCache->nextXid,
84858488
checkPoint.nextXid))
84868489
ShmemVariableCache->nextXid = checkPoint.nextXid;
8487-
if (ShmemVariableCache->nextOid < checkPoint.nextOid)
8488-
{
8489-
ShmemVariableCache->nextOid = checkPoint.nextOid;
8490-
ShmemVariableCache->oidCount = 0;
8491-
}
8490+
/* ... but still treat OID counter as exact */
8491+
ShmemVariableCache->nextOid = checkPoint.nextOid;
8492+
ShmemVariableCache->oidCount = 0;
84928493
MultiXactAdvanceNextMXact(checkPoint.nextMulti,
84938494
checkPoint.nextMultiOffset);
84948495
if (TransactionIdPrecedes(ShmemVariableCache->oldestXid,

0 commit comments

Comments
 (0)