8000 Ensure no xid gaps during Hot Standby startup · kosalalakshitha/postgres@99ee15b · GitHub
[go: up one dir, main page]

Skip to content

Commit 99ee15b

Browse files
Ensure no xid gaps during Hot Standby startup
In some cases with higher numbers of subtransactions it was possible for us to incorrectly initialize subtrans leading to complaints of missing pages. Bug report by Sergey Konoplev Analysis and fix by Andres Freund
1 parent 73c103d commit 99ee15b

File tree

3 files changed

+51
-6
lines changed

3 files changed

+51
-6
lines changed

src/backend/access/transam/xlog.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6692,6 +6692,9 @@ StartupXLOG(void)
66926692
oldestActiveXID = checkPoint.oldestActiveXid;
66936693
Assert(TransactionIdIsValid(oldestActiveXID));
66946694

6695+
/* Tell procarray about the range of xids it has to deal with */
6696+
ProcArrayInitRecovery(ShmemVariableCache->nextXid);
6697+
66956698
/*
66966699
* Startup commit log and subtrans only. Other SLRUs are not
66976700
* maintained during recovery and need not be started yet.

src/backend/storage/ipc/procarray.c

Lines changed: 47 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -468,6 +468,28 @@ ProcArrayClearTransaction(PGPROC *proc)
468468
pgxact->overflowed = false;
469469
}
470470

471+
/*
472+
* ProcArrayInitRecovery -- initialize recovery xid mgmt environment
473+
*
474+
* Remember up to where the startup process initialized the CLOG and subtrans
475+
* s 10000 o we can ensure its initialized gaplessly up to the point where necessary
476+
* while in recovery.
477+
*/
478+
void
479+
ProcArrayInitRecovery(TransactionId initializedUptoXID)
480+
{
481+
Assert(standbyState == STANDBY_INITIALIZED);
482+
Assert(TransactionIdIsNormal(initializedUptoXID));
483+
484+
/*
485+
* we set latestObservedXid to the xid SUBTRANS has been initialized upto
486+
* so we can extend it from that point onwards when we reach a consistent
487+
* state in ProcArrayApplyRecoveryInfo().
488+
*/
489+
latestObservedXid = initializedUptoXID;
490+
TransactionIdRetreat(latestObservedXid);
491+
}
492+
471493
/*
472494
* ProcArrayApplyRecoveryInfo -- apply recovery info about xids
473495
*
@@ -556,7 +578,10 @@ ProcArrayApplyRecoveryInfo(RunningTransactions running)
556578
Assert(standbyState == STANDBY_INITIALIZED);
557579

558580
/*
559-
* OK, we need to initialise from the RunningTransactionsData record
581+
* OK, we need to initialise from the RunningTransactionsData record.
582+
*
583+
* NB: this can be reached at least twice, so make sure new code can deal
584+
* with that.
560585
*/
561586

562587
/*
@@ -628,20 +653,32 @@ ProcArrayApplyRecoveryInfo(RunningTransactions running)
628653
pfree(xids);
629654

630655
/*
656+
* latestObservedXid is set to the the point where SUBTRANS was started up
657+
* to, initialize subtrans from thereon, up to nextXid - 1.
658+
*/
659+
Assert(TransactionIdIsNormal(latestObservedXid));
660+
while (TransactionIdPrecedes(latestObservedXid, running->nextXid))
661+
{
662+
ExtendCLOG(latestObservedXid);
663+
ExtendSUBTRANS(latestObservedXid);
664+
665+
TransactionIdAdvance(latestObservedXid);
666+
}
667+
668+
/* ----------
631669
* Now we've got the running xids we need to set the global values that
632670
* are used to track snapshots as they evolve further.
633671
*
634-
* - latestCompletedXid which will be the xmax for snapshots -
635-
* lastOverflowedXid which shows whether snapshots overflow - nextXid
672+
* - latestCompletedXid which will be the xmax for snapshots
673+
* - lastOverflowedXid which shows whether snapshots overflow
674+
* - nextXid
636675
*
637676
* If the snapshot overflowed, then we still initialise with what we know,
638677
* but the recovery snapshot isn't fully valid yet because we know there
639678
* are some subxids missing. We don't know the specific subxids that are
640679
* missing, so conservatively assume the last one is latestObservedXid.
680+
* ----------
641681
*/
642-
latestObservedXid = running->nextXid;
643-
TransactionIdRetreat(latestObservedXid);
644-
645682
if (running->subxid_overflow)
646683
{
647684
standbyState = STANDBY_SNAPSHOT_PENDING;
@@ -711,6 +748,10 @@ ProcArrayApplyXidAssignment(TransactionId topxid,
711748

712749
Assert(standbyState >= STANDBY_INITIALIZED);
713750

751+
/* can't do anything useful unless we have more state setup */
752+
if (standbyState == STANDBY_INITIALIZED)
753+
return;
754+
714755
max_xid = TransactionIdLatest(topxid, nsubxids, subxids);
715756

716757
/*

src/include/storage/procarray.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ extern void ProcArrayRemove(PGPROC *proc, TransactionId latestXid);
2626
extern void ProcArrayEndTransaction(PGPROC *proc, TransactionId latestXid);
2727
extern void ProcArrayClearTransaction(PGPROC *proc);
2828

29+
extern void ProcArrayInitRecovery(TransactionId initializedUptoXID);
2930
extern void ProcArrayApplyRecoveryInfo(RunningTransactions running);
3031
extern void ProcArrayApplyXidAssignment(TransactionId topxid,
3132
int nsubxids, TransactionId *subxids);

0 commit comments

Comments
 (0)
0