diff --git a/src/backend/access/transam/multixact.c b/src/backend/access/transam/multixact.c
index 59d1252..3f66cdb 100644
*** a/src/backend/access/transam/multixact.c
--- b/src/backend/access/transam/multixact.c
*************** static void ExtendMultiXactOffset(MultiX
*** 363,369 ****
  static void ExtendMultiXactMember(MultiXactOffset offset, int nmembers);
  static bool MultiXactOffsetWouldWrap(MultiXactOffset boundary,
  						 MultiXactOffset start, uint32 distance);
! static bool SetOffsetVacuumLimit(void);
  static bool find_multixact_start(MultiXactId multi, MultiXactOffset *result);
  static void WriteMZeroPageXlogRec(int pageno, uint8 info);
  static void WriteMTruncateXlogRec(Oid oldestMultiDB,
--- 363,369 ----
  static void ExtendMultiXactMember(MultiXactOffset offset, int nmembers);
  static bool MultiXactOffsetWouldWrap(MultiXactOffset boundary,
  						 MultiXactOffset start, uint32 distance);
! static bool SetOffsetVacuumLimit(bool is_startup);
  static bool find_multixact_start(MultiXactId multi, MultiXactOffset *result);
  static void WriteMZeroPageXlogRec(int pageno, uint8 info);
  static void WriteMTruncateXlogRec(Oid oldestMultiDB,
*************** TrimMultiXact(void)
*** 2095,2101 ****
  	LWLockRelease(MultiXactGenLock);
  
  	/* Now compute how far away the next members wraparound is. */
! 	SetMultiXactIdLimit(oldestMXact, oldestMXactDB);
  }
  
  /*
--- 2095,2101 ----
  	LWLockRelease(MultiXactGenLock);
  
  	/* Now compute how far away the next members wraparound is. */
! 	SetMultiXactIdLimit(oldestMXact, oldestMXactDB, true);
  }
  
  /*
*************** MultiXactSetNextMXact(MultiXactId nextMu
*** 2186,2194 ****
   * Determine the last safe MultiXactId to allocate given the currently oldest
   * datminmxid (ie, the oldest MultiXactId that might exist in any database
   * of our cluster), and the OID of the (or a) database with that value.
   */
  void
! SetMultiXactIdLimit(MultiXactId oldest_datminmxid, Oid oldest_datoid)
  {
  	MultiXactId multiVacLimit;
  	MultiXactId multiWarnLimit;
--- 2186,2198 ----
   * Determine the last safe MultiXactId to allocate given the currently oldest
   * datminmxid (ie, the oldest MultiXactId that might exist in any database
   * of our cluster), and the OID of the (or a) database with that value.
+  *
+  * is_startup is true when we are just starting the cluster, false when we
+  * are updating state in a running cluster.  This only affects log messages.
   */
  void
! SetMultiXactIdLimit(MultiXactId oldest_datminmxid, Oid oldest_datoid,
! 					bool is_startup)
  {
  	MultiXactId multiVacLimit;
  	MultiXactId multiWarnLimit;
*************** SetMultiXactIdLimit(MultiXactId oldest_d
*** 2277,2283 ****
  	Assert(!InRecovery);
  
  	/* Set limits for offset vacuum. */
! 	needs_offset_vacuum = SetOffsetVacuumLimit();
  
  	/*
  	 * If past the autovacuum force point, immediately signal an autovac
--- 2281,2287 ----
  	Assert(!InRecovery);
  
  	/* Set limits for offset vacuum. */
! 	needs_offset_vacuum = SetOffsetVacuumLimit(is_startup);
  
  	/*
  	 * If past the autovacuum force point, immediately signal an autovac
*************** MultiXactAdvanceOldest(MultiXactId oldes
*** 2370,2376 ****
  	Assert(InRecovery);
  
  	if (MultiXactIdPrecedes(MultiXactState->oldestMultiXactId, oldestMulti))
! 		SetMultiXactIdLimit(oldestMulti, oldestMultiDB);
  }
  
  /*
--- 2374,2380 ----
  	Assert(InRecovery);
  
  	if (MultiXactIdPrecedes(MultiXactState->oldestMultiXactId, oldestMulti))
! 		SetMultiXactIdLimit(oldestMulti, oldestMultiDB, false);
  }
  
  /*
*************** GetOldestMultiXactId(void)
*** 2537,2543 ****
   * otherwise.
   */
  static bool
! SetOffsetVacuumLimit(void)
  {
  	MultiXactId oldestMultiXactId;
  	MultiXactId nextMXact;
--- 2541,2547 ----
   * otherwise.
   */
  static bool
! SetOffsetVacuumLimit(bool is_startup)
  {
  	MultiXactId oldestMultiXactId;
  	MultiXactId nextMXact;
*************** SetOffsetVacuumLimit(void)
*** 2619,2627 ****
  		/* always leave one segment before the wraparound point */
  		offsetStopLimit -= (MULTIXACT_MEMBERS_PER_PAGE * SLRU_PAGES_PER_SEGMENT);
  
! 		if (!prevOldestOffsetKnown && IsUnderPostmaster)
  			ereport(LOG,
  					(errmsg("MultiXact member wraparound protections are now enabled")));
  		ereport(DEBUG1,
  		(errmsg("MultiXact member stop limit is now %u based on MultiXact %u",
  				offsetStopLimit, oldestMultiXactId)));
--- 2623,2632 ----
  		/* always leave one segment before the wraparound point */
  		offsetStopLimit -= (MULTIXACT_MEMBERS_PER_PAGE * SLRU_PAGES_PER_SEGMENT);
  
! 		if (!prevOldestOffsetKnown && !is_startup)
  			ereport(LOG,
  					(errmsg("MultiXact member wraparound protections are now enabled")));
+ 
  		ereport(DEBUG1,
  		(errmsg("MultiXact member stop limit is now %u based on MultiXact %u",
  				offsetStopLimit, oldestMultiXactId)));
*************** SetOffsetVacuumLimit(void)
*** 2639,2644 ****
--- 2644,2654 ----
  		offsetStopLimit = prevOffsetStopLimit;
  	}
  
+ 	/* Warn at startup if wraparound protection isn't active */
+ 	if (is_startup && !oldestOffsetKnown)
+ 		ereport(LOG,
+ 		 (errmsg("MultiXact member wraparound protections are not active")));
+ 
  	/* Install the computed values */
  	LWLockAcquire(MultiXactGenLock, LW_EXCLUSIVE);
  	MultiXactState->oldestOffset = oldestOffset;
*************** multixact_redo(XLogReaderState *record)
*** 3312,3318 ****
  		 * Advance the horizon values, so they're current at the end of
  		 * recovery.
  		 */
! 		SetMultiXactIdLimit(xlrec.endTruncOff, xlrec.oldestMultiDB);
  
  		PerformMembersTruncation(xlrec.startTruncMemb, xlrec.endTruncMemb);
  
--- 3322,3328 ----
  		 * Advance the horizon values, so they're current at the end of
  		 * recovery.
  		 */
! 		SetMultiXactIdLimit(xlrec.endTruncOff, xlrec.oldestMultiDB, false);
  
  		PerformMembersTruncation(xlrec.startTruncMemb, xlrec.endTruncMemb);
  
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 744360c..299ce30 100644
*** a/src/backend/access/transam/xlog.c
--- b/src/backend/access/transam/xlog.c
*************** BootStrapXLOG(void)
*** 4995,5001 ****
  	ShmemVariableCache->oidCount = 0;
  	MultiXactSetNextMXact(checkPoint.nextMulti, checkPoint.nextMultiOffset);
  	SetTransactionIdLimit(checkPoint.oldestXid, checkPoint.oldestXidDB);
! 	SetMultiXactIdLimit(checkPoint.oldestMulti, checkPoint.oldestMultiDB);
  	SetCommitTsLimit(InvalidTransactionId, InvalidTransactionId);
  
  	/* Set up the XLOG page header */
--- 4995,5001 ----
  	ShmemVariableCache->oidCount = 0;
  	MultiXactSetNextMXact(checkPoint.nextMulti, checkPoint.nextMultiOffset);
  	SetTransactionIdLimit(checkPoint.oldestXid, checkPoint.oldestXidDB);
! 	SetMultiXactIdLimit(checkPoint.oldestMulti, checkPoint.oldestMultiDB, true);
  	SetCommitTsLimit(InvalidTransactionId, InvalidTransactionId);
  
  	/* Set up the XLOG page header */
*************** StartupXLOG(void)
*** 6597,6603 ****
  	ShmemVariableCache->oidCount = 0;
  	MultiXactSetNextMXact(checkPoint.nextMulti, checkPoint.nextMultiOffset);
  	SetTransactionIdLimit(checkPoint.oldestXid, checkPoint.oldestXidDB);
! 	SetMultiXactIdLimit(checkPoint.oldestMulti, checkPoint.oldestMultiDB);
  	SetCommitTsLimit(checkPoint.oldestCommitTsXid,
  					 checkPoint.newestCommitTsXid);
  	XLogCtl->ckptXidEpoch = checkPoint.nextXidEpoch;
--- 6597,6603 ----
  	ShmemVariableCache->oidCount = 0;
  	MultiXactSetNextMXact(checkPoint.nextMulti, checkPoint.nextMultiOffset);
  	SetTransactionIdLimit(checkPoint.oldestXid, checkPoint.oldestXidDB);
! 	SetMultiXactIdLimit(checkPoint.oldestMulti, checkPoint.oldestMultiDB, true);
  	SetCommitTsLimit(checkPoint.oldestCommitTsXid,
  					 checkPoint.newestCommitTsXid);
  	XLogCtl->ckptXidEpoch = checkPoint.nextXidEpoch;
diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 3a9b965..3b3dfee 100644
*** a/src/backend/commands/vacuum.c
--- b/src/backend/commands/vacuum.c
*************** vac_truncate_clog(TransactionId frozenXI
*** 1205,1211 ****
  	 * signalling twice?
  	 */
  	SetTransactionIdLimit(frozenXID, oldestxid_datoid);
! 	SetMultiXactIdLimit(minMulti, minmulti_datoid);
  }
  
  
--- 1205,1211 ----
  	 * signalling twice?
  	 */
  	SetTransactionIdLimit(frozenXID, oldestxid_datoid);
! 	SetMultiXactIdLimit(minMulti, minmulti_datoid, false);
  }
  
  
diff --git a/src/include/access/multixact.h b/src/include/access/multixact.h
index 1d01988..85997a4 100644
*** a/src/include/access/multixact.h
--- b/src/include/access/multixact.h
*************** extern void StartupMultiXact(void);
*** 127,133 ****
  extern void TrimMultiXact(void);
  extern void ShutdownMultiXact(void);
  extern void SetMultiXactIdLimit(MultiXactId oldest_datminmxid,
! 					Oid oldest_datoid);
  extern void MultiXactGetCheckptMulti(bool is_shutdown,
  						 MultiXactId *nextMulti,
  						 MultiXactOffset *nextMultiOffset,
--- 127,134 ----
  extern void TrimMultiXact(void);
  extern void ShutdownMultiXact(void);
  extern void SetMultiXactIdLimit(MultiXactId oldest_datminmxid,
! 					Oid oldest_datoid,
! 					bool is_startup);
  extern void MultiXactGetCheckptMulti(bool is_shutdown,
  						 MultiXactId *nextMulti,
  						 MultiXactOffset *nextMultiOffset,
