*** a/src/backend/access/transam/clog.c --- b/src/backend/access/transam/clog.c *************** *** 355,364 **** TransactionIdSetStatusBit(TransactionId xid, XidStatus status, XLogRecPtr lsn, i /* * Update the group LSN if the transaction completion LSN is higher. * ! * Note: lsn will be invalid when supplied during InRecovery processing, ! * so we don't need to do anything special to avoid LSN updates during ! * recovery. After recovery completes the next clog change will set the ! * LSN correctly. */ if (!XLogRecPtrIsInvalid(lsn)) { --- 355,364 ---- /* * Update the group LSN if the transaction completion LSN is higher. * ! * Note: lsn will be invalid when supplied while we're performing ! * recovery but hot standby is disabled, so we don't need to do ! * anything special to avoid LSN updates in that case. After recovery ! * completes the next clog change will set the LSN correctly. */ if (!XLogRecPtrIsInvalid(lsn)) { *** a/src/backend/access/transam/xact.c --- b/src/backend/access/transam/xact.c *************** *** 4522,4530 **** xact_redo_abort(xl_xact_abort *xlrec, TransactionId xid) sub_xids = (TransactionId *) &(xlrec->xnodes[xlrec->nrels]); max_xid = TransactionIdLatest(xid, xlrec->nsubxacts, sub_xids); - /* Make sure nextXid is beyond any XID mentioned in the record */ - /* * We don't expect anyone else to modify nextXid, hence we don't need to * hold a lock while checking this. We still acquire the lock to modify * it, though. --- 4522,4530 ---- sub_xids = (TransactionId *) &(xlrec->xnodes[xlrec->nrels]); max_xid = TransactionIdLatest(xid, xlrec->nsubxacts, sub_xids); /* + * Make sure nextXid is beyond any XID mentioned in the record. + * * We don't expect anyone else to modify nextXid, hence we don't need to * hold a lock while checking this. We still acquire the lock to modify * it, though. *** a/src/backend/storage/ipc/procarray.c --- b/src/backend/storage/ipc/procarray.c *************** *** 449,455 **** ProcArrayInitRecoveryInfo(TransactionId oldestActiveXid) /* * ProcArrayApplyRecoveryInfo -- apply recovery info about xids * ! * Takes us through 3 states: Uninitialized, Pending and Ready. * Normal case is to go all the way to Ready straight away, though there * are atypical cases where we need to take it in steps. * --- 449,455 ---- /* * ProcArrayApplyRecoveryInfo -- apply recovery info about xids * ! * Takes us through 3 states: Initialized, Pending and Ready. * Normal case is to go all the way to Ready straight away, though there * are atypical cases where we need to take it in steps. * *************** *** 487,493 **** ProcArrayApplyRecoveryInfo(RunningTransactions running) return; /* ! * If our initial RunningXactData had an overflowed snapshot then we knew * we were missing some subxids from our snapshot. We can use this data as * an initial snapshot, but we cannot yet mark it valid. We know that the * missing subxids are equal to or earlier than nextXid. After we --- 487,493 ---- return; /* ! * If our initial RunningTransactionsData had an overflowed snapshot then we knew * we were missing some subxids from our snapshot. We can use this data as * an initial snapshot, but we cannot yet mark it valid. We know that the * missing subxids are equal to or earlier than nextXid. After we *************** *** 518,524 **** ProcArrayApplyRecoveryInfo(RunningTransactions running) Assert(standbyState == STANDBY_INITIALIZED); /* ! * OK, we need to initialise from the RunningXactData record */ /* --- 518,524 ---- Assert(standbyState == STANDBY_INITIALIZED); /* ! * OK, we need to initialise from the RunningTransactionsData record */ /* *************** *** 1499,1505 **** GetRunningTransactionData(void) suboverflowed = true; /* ! * Top-level XID of a transaction is always greater than any of * its subxids, so we don't need to check if any of the subxids * are smaller than oldestRunningXid */ --- 1499,1505 ---- suboverflowed = true; /* ! * Top-level XID of a transaction is always less than any of * its subxids, so we don't need to check if any of the subxids * are smaller than oldestRunningXid */ *************** *** 2313,2319 **** DisplayXidCache(void) * aborted but we think they were running; the distinction is irrelevant * because either way any changes done by the transaction are not visible to * backends in the standby. We prune KnownAssignedXids when ! * XLOG_XACT_RUNNING_XACTS arrives, to forestall possible overflow of the * array due to such dead XIDs. */ --- 2313,2319 ---- * aborted but we think they were running; the distinction is irrelevant * because either way any changes done by the transaction are not visible to * backends in the standby. We prune KnownAssignedXids when ! * XLOG_RUNNING_XACTS arrives, to forestall possible overflow of the * array due to such dead XIDs. */ *************** *** 2323,2331 **** DisplayXidCache(void) * unobserved XIDs. * * RecordKnownAssignedTransactionIds() should be run for *every* WAL record ! * type apart from XLOG_XACT_RUNNING_XACTS (since that initialises the first * snapshot so that RecordKnownAssignedTransactionIds() can be called). Must ! * be called for each record after we have executed StartupCLog() et al, * since we must ExtendCLOG() etc.. * * Called during recovery in analogy with and in place of GetNewTransactionId() --- 2323,2331 ---- * unobserved XIDs. * * RecordKnownAssignedTransactionIds() should be run for *every* WAL record ! * type apart from XLOG_RUNNING_XACTS (since that initialises the first * snapshot so that RecordKnownAssignedTransactionIds() can be called). Must ! * be called for each record after we have executed StartupCLOG() et al, * since we must ExtendCLOG() etc.. * * Called during recovery in analogy with and in place of GetNewTransactionId() *************** *** 3046,3056 **** KnownAssignedXidsDisplay(int trace_level) if (KnownAssignedXidsValid[i]) { nxids++; ! appendStringInfo(&buf, "[%u]=%u ", i, KnownAssignedXids[i]); } } ! elog(trace_level, "%d KnownAssignedXids (num=%u tail=%u head=%u) %s", nxids, pArray->numKnownAssignedXids, pArray->tailKnownAssignedXids, --- 3046,3056 ---- if (KnownAssignedXidsValid[i]) { nxids++; ! appendStringInfo(&buf, "[%d]=%u ", i, KnownAssignedXids[i]); } } ! elog(trace_level, "%d KnownAssignedXids (num=%d tail=%d head=%d) %s", nxids, pArray->numKnownAssignedXids, pArray->tailKnownAssignedXids, *** a/src/backend/storage/ipc/standby.c --- b/src/backend/storage/ipc/standby.c *************** *** 522,528 **** CheckRecoveryConflictDeadlock(LWLockId partitionLock) * one transaction on one relation, and don't worry about lock queuing. * * We keep a single dynamically expandible list of locks in local memory, ! * RelationLockList, so we can keep track of the various entried made by * the Startup process's virtual xid in the shared lock table. * * List elements use type xl_rel_lock, since the WAL record type exactly --- 522,528 ---- * one transaction on one relation, and don't worry about lock queuing. * * We keep a single dynamically expandible list of locks in local memory, ! * RelationLockList, so we can keep track of the various entries made by * the Startup process's virtual xid in the shared lock table. * * List elements use type xl_rel_lock, since the WAL record type exactly *************** *** 700,706 **** standby_redo(XLogRecPtr lsn, XLogRecord *record) { uint8 info = record->xl_info & ~XLR_INFO_MASK; ! /* Do nothing if we're not in standby mode */ if (standbyState == STANDBY_DISABLED) return; --- 700,706 ---- { uint8 info = record->xl_info & ~XLR_INFO_MASK; ! /* Do nothing if we're not in hot standby mode */ if (standbyState == STANDBY_DISABLED) return; *************** *** 872,878 **** LogStandbySnapshot(TransactionId *oldestActiveXid, TransactionId *nextXid) /* * Record an enhanced snapshot of running transactions into WAL. * ! * The definitions of RunningTransactionData and xl_xact_running_xacts * are similar. We keep them separate because xl_xact_running_xacts * is a contiguous chunk of memory and never exists fully until it is * assembled in WAL. --- 872,878 ---- /* * Record an enhanced snapshot of running transactions into WAL. * ! * The definitions of RunningTransactionsData and xl_xact_running_xacts * are similar. We keep them separate because xl_xact_running_xacts * is a contiguous chunk of memory and never exists fully until it is * assembled in WAL. *** a/src/backend/tcop/postgres.c --- b/src/backend/tcop/postgres.c *************** *** 2741,2747 **** SigHupHandler(SIGNAL_ARGS) /* * RecoveryConflictInterrupt: out-of-line portion of recovery conflict ! * handling ollowing receipt of SIGUSR1. Designed to be similar to die() * and StatementCancelHandler(). Called only by a normal user backend * that begins a transaction during recovery. */ --- 2741,2747 ---- /* * RecoveryConflictInterrupt: out-of-line portion of recovery conflict ! * handling following receipt of SIGUSR1. Designed to be similar to die() * and StatementCancelHandler(). Called only by a normal user backend * that begins a transaction during recovery. */ *** a/src/include/access/xlog.h --- b/src/include/access/xlog.h *************** *** 149,155 **** extern bool InRecovery; * InHotStandby will read as FALSE). * * In DISABLED state, we're performing crash recovery or hot standby was ! * disabled in recovery.conf. * * In INITIALIZED state, we've run InitRecoveryTransactionEnvironment, but * we haven't yet processed a RUNNING_XACTS or shutdown-checkpoint WAL record --- 149,155 ---- * InHotStandby will read as FALSE). * * In DISABLED state, we're performing crash recovery or hot standby was ! * disabled in postgresql.conf. * * In INITIALIZED state, we've run InitRecoveryTransactionEnvironment, but * we haven't yet processed a RUNNING_XACTS or shutdown-checkpoint WAL record *** a/src/include/catalog/pg_control.h --- b/src/include/catalog/pg_control.h *************** *** 45,51 **** typedef struct CheckPoint /* * Oldest XID still running. This is only needed to initialize hot standby * mode from an online checkpoint, so we only bother calculating this for ! * online checkpoints and only when archiving is enabled. Otherwise it's * set to InvalidTransactionId. */ TransactionId oldestActiveXid; --- 45,51 ---- /* * Oldest XID still running. This is only needed to initialize hot standby * mode from an online checkpoint, so we only bother calculating this for ! * online checkpoints and only when wal_level is hot_standby. Otherwise it's * set to InvalidTransactionId. */ TransactionId oldestActiveXid;