@@ -435,6 +435,28 @@ ProcArrayClearTransaction(PGPROC *proc)
435435proc -> subxids .overflowed = false;
436436}
437437
438+ /*
439+ * ProcArrayInitRecovery -- initialize recovery xid mgmt environment
440+ *
441+ * Remember up to where the startup process initialized the CLOG and subtrans
442+ * so we can ensure its initialized gaplessly up to the point where necessary
443+ * while in recovery.
444+ */
445+ void
446+ ProcArrayInitRecovery (TransactionId initializedUptoXID )
447+ {
448+ Assert (standbyState == STANDBY_INITIALIZED );
449+ Assert (TransactionIdIsNormal (initializedUptoXID ));
450+
451+ /*
452+ * we set latestObservedXid to the xid SUBTRANS has been initialized upto
453+ * so we can extend it from that point onwards when we reach a consistent
454+ * state in ProcArrayApplyRecoveryInfo().
455+ */
456+ latestObservedXid = initializedUptoXID ;
457+ TransactionIdRetreat (latestObservedXid );
458+ }
459+
438460/*
439461 * ProcArrayApplyRecoveryInfo -- apply recovery info about xids
440462 *
@@ -523,7 +545,10 @@ ProcArrayApplyRecoveryInfo(RunningTransactions running)
523545Assert (standbyState == STANDBY_INITIALIZED );
524546
525547/*
526- * OK, we need to initialise from the RunningTransactionsData record
548+ * OK, we need to initialise from the RunningTransactionsData record.
549+ *
550+ * NB: this can be reached at least twice, so make sure new code can deal
551+ * with that.
527552 */
528553
529554/*
@@ -595,20 +620,32 @@ ProcArrayApplyRecoveryInfo(RunningTransactions running)
595620pfree (xids );
596621
597622/*
623+ * latestObservedXid is set to the the point where SUBTRANS was started up
624+ * to, initialize subtrans from thereon, up to nextXid - 1.
625+ */
626+ Assert (TransactionIdIsNormal (latestObservedXid ));
627+ while (TransactionIdPrecedes (latestObservedXid ,running -> nextXid ))
628+ {
629+ ExtendCLOG (latestObservedXid );
630+ ExtendSUBTRANS (latestObservedXid );
631+
632+ TransactionIdAdvance (latestObservedXid );
633+ }
634+
635+ /* ----------
598636 * Now we've got the running xids we need to set the global values that
599637 * are used to track snapshots as they evolve further.
600638 *
601- * - latestCompletedXid which will be the xmax for snapshots -
602- * lastOverflowedXid which shows whether snapshots overflow - nextXid
639+ * - latestCompletedXid which will be the xmax for snapshots
640+ * - lastOverflowedXid which shows whether snapshots overflow
641+ * - nextXid
603642 *
604643 * If the snapshot overflowed, then we still initialise with what we know,
605644 * but the recovery snapshot isn't fully valid yet because we know there
606645 * are some subxids missing. We don't know the specific subxids that are
607646 * missing, so conservatively assume the last one is latestObservedXid.
647+ * ----------
608648 */
609- latestObservedXid = running -> nextXid ;
610- TransactionIdRetreat (latestObservedXid );
611-
612649if (running -> subxid_overflow )
613650{
614651standbyState = STANDBY_SNAPSHOT_PENDING ;
@@ -667,6 +704,10 @@ ProcArrayApplyXidAssignment(TransactionId topxid,
667704
668705Assert (standbyState >=STANDBY_INITIALIZED );
669706
707+ /* can't do anything useful unless we have more state setup */
708+ if (standbyState == STANDBY_INITIALIZED )
709+ return ;
710+
670711max_xid = TransactionIdLatest (topxid ,nsubxids ,subxids );
671712
672713/*