@@ -468,6 +468,28 @@ ProcArrayClearTransaction(PGPROC *proc)
468468pgxact -> 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+ * so 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)
556578Assert (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)
628653pfree (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-
645682if (running -> subxid_overflow )
646683{
647684standbyState = STANDBY_SNAPSHOT_PENDING ;
@@ -711,6 +748,10 @@ ProcArrayApplyXidAssignment(TransactionId topxid,
711748
712749Assert (standbyState >=STANDBY_INITIALIZED );
713750
751+ /* can't do anything useful unless we have more state setup */
752+ if (standbyState == STANDBY_INITIALIZED )
753+ return ;
754+
714755max_xid = TransactionIdLatest (topxid ,nsubxids ,subxids );
715756
716757/*