@@ -469,6 +469,28 @@ ProcArrayClearTransaction(PGPROC *proc)
469469 pgxact -> overflowed = false;
470470}
471471
472+ /*
473+ * ProcArrayInitRecovery -- initialize recovery xid mgmt environment
474+ *
475+ * Remember up to where the startup process initialized the CLOG and subtrans
476+ * so we can ensure its initialized gaplessly up to the point where necessary
477+ * while in recovery.
478+ */
479+ void
480+ ProcArrayInitRecovery (TransactionId initializedUptoXID )
481+ {
482+ Assert (standbyState == STANDBY_INITIALIZED );
483+ Assert (TransactionIdIsNormal (initializedUptoXID ));
484+
485+ /*
486+ * we set latestObservedXid to the xid SUBTRANS has been initialized upto
487+ * so we can extend it from that point onwards when we reach a consistent
488+ * state in ProcArrayApplyRecoveryInfo().
489+ */
490+ latestObservedXid = initializedUptoXID ;
491+ TransactionIdRetreat (latestObservedXid );
492+ }
493+
472494/*
473495 * ProcArrayApplyRecoveryInfo -- apply recovery info about xids
474496 *
@@ -564,7 +586,10 @@ ProcArrayApplyRecoveryInfo(RunningTransactions running)
564586 Assert (standbyState == STANDBY_INITIALIZED );
565587
566588 /*
567- * OK, we need to initialise from the RunningTransactionsData record
589+ * OK, we need to initialise from the RunningTransactionsData record.
590+ *
591+ * NB: this can be reached at least twice, so make sure new code can deal
592+ * with that.
568593 */
569594
570595 /*
@@ -636,20 +661,32 @@ ProcArrayApplyRecoveryInfo(RunningTransactions running)
636661 pfree (xids );
637662
638663 /*
664+ * latestObservedXid is set to the the point where SUBTRANS was started up
665+ * to, initialize subtrans from thereon, up to nextXid - 1.
666+ */
667+ Assert (TransactionIdIsNormal (latestObservedXid ));
668+ while (TransactionIdPrecedes (latestObservedXid , running -> nextXid ))
669+ {
670+ ExtendCLOG (latestObservedXid );
671+ ExtendSUBTRANS (latestObservedXid );
672+
673+ TransactionIdAdvance (latestObservedXid );
674+ }
675+
676+ /* ----------
639677 * Now we've got the running xids we need to set the global values that
640678 * are used to track snapshots as they evolve further.
641679 *
642- * - latestCompletedXid which will be the xmax for snapshots -
643- * lastOverflowedXid which shows whether snapshots overflow - nextXid
680+ * - latestCompletedXid which will be the xmax for snapshots
681+ * - lastOverflowedXid which shows whether snapshots overflow
682+ * - nextXid
644683 *
645684 * If the snapshot overflowed, then we still initialise with what we know,
646685 * but the recovery snapshot isn't fully valid yet because we know there
647686 * are some subxids missing. We don't know the specific subxids that are
648687 * missing, so conservatively assume the last one is latestObservedXid.
688+ * ----------
649689 */
650- latestObservedXid = running -> nextXid ;
651- TransactionIdRetreat (latestObservedXid );
652-
653690 if (running -> subxid_overflow )
654691 {
655692 standbyState = STANDBY_SNAPSHOT_PENDING ;
@@ -719,6 +756,10 @@ ProcArrayApplyXidAssignment(TransactionId topxid,
719756
720757 Assert (standbyState >= STANDBY_INITIALIZED );
721758
759+ /* can't do anything useful unless we have more state setup */
760+ if (standbyState == STANDBY_INITIALIZED )
761+ return ;
762+
722763 max_xid = TransactionIdLatest (topxid , nsubxids , subxids );
723764
724765 /*
0 commit comments