mirror of
				https://github.com/postgres/postgres.git
				synced 2025-11-04 00:02:52 -05:00 
			
		
		
		
	Skip WAL recycling and preallocation during archive recovery.
The previous commit addressed the chief consequences of a race condition between InstallXLogFileSegment() and KeepFileRestoredFromArchive(). Fix three lesser consequences. A spurious durable_rename_excl() LOG message remained possible. KeepFileRestoredFromArchive() wasted the proceeds of WAL recycling and preallocation. Finally, XLogFileInitInternal() could return a descriptor for a file that KeepFileRestoredFromArchive() had already unlinked. That felt like a recipe for future bugs. Discussion: https://postgr.es/m/20210202151416.GB3304930@rfd.leadboat.com
This commit is contained in:
		
							parent
							
								
									2b3e4672f7
								
							
						
					
					
						commit
						cc2c7d65fc
					
				@ -662,6 +662,16 @@ typedef struct XLogCtlData
 | 
			
		||||
	 */
 | 
			
		||||
	bool		SharedHotStandbyActive;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * InstallXLogFileSegmentActive indicates whether the checkpointer should
 | 
			
		||||
	 * arrange for future segments by recycling and/or PreallocXlogFiles().
 | 
			
		||||
	 * Protected by ControlFileLock.  Only the startup process changes it.  If
 | 
			
		||||
	 * true, anyone can use InstallXLogFileSegment().  If false, the startup
 | 
			
		||||
	 * process owns the exclusive right to install segments, by reading from
 | 
			
		||||
	 * the archive and possibly replacing existing files.
 | 
			
		||||
	 */
 | 
			
		||||
	bool		InstallXLogFileSegmentActive;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * SharedPromoteIsTriggered indicates if a standby promotion has been
 | 
			
		||||
	 * triggered.  Protected by info_lck.
 | 
			
		||||
@ -921,6 +931,7 @@ static int	XLogPageRead(XLogReaderState *xlogreader, XLogRecPtr targetPagePtr,
 | 
			
		||||
						 int reqLen, XLogRecPtr targetRecPtr, char *readBuf);
 | 
			
		||||
static bool WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool randAccess,
 | 
			
		||||
										bool fetching_ckpt, XLogRecPtr tliRecPtr);
 | 
			
		||||
static void XLogShutdownWalRcv(void);
 | 
			
		||||
static int	emode_for_corrupt_record(int emode, XLogRecPtr RecPtr);
 | 
			
		||||
static void XLogFileClose(void);
 | 
			
		||||
static void PreallocXlogFiles(XLogRecPtr endptr);
 | 
			
		||||
@ -3625,8 +3636,8 @@ XLogFileCopy(XLogSegNo destsegno, TimeLineID srcTLI, XLogSegNo srcsegno,
 | 
			
		||||
 * is false.)
 | 
			
		||||
 *
 | 
			
		||||
 * Returns true if the file was installed successfully.  false indicates that
 | 
			
		||||
 * max_segno limit was exceeded, or an error occurred while renaming the
 | 
			
		||||
 * file into place.
 | 
			
		||||
 * max_segno limit was exceeded, the startup process has disabled this
 | 
			
		||||
 * function for now, or an error occurred while renaming the file into place.
 | 
			
		||||
 */
 | 
			
		||||
static bool
 | 
			
		||||
InstallXLogFileSegment(XLogSegNo *segno, char *tmppath,
 | 
			
		||||
@ -3638,6 +3649,11 @@ InstallXLogFileSegment(XLogSegNo *segno, char *tmppath,
 | 
			
		||||
	XLogFilePath(path, ThisTimeLineID, *segno, wal_segment_size);
 | 
			
		||||
 | 
			
		||||
	LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
 | 
			
		||||
	if (!XLogCtl->InstallXLogFileSegmentActive)
 | 
			
		||||
	{
 | 
			
		||||
		LWLockRelease(ControlFileLock);
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!find_free)
 | 
			
		||||
	{
 | 
			
		||||
@ -3745,6 +3761,7 @@ XLogFileRead(XLogSegNo segno, int emode, TimeLineID tli,
 | 
			
		||||
	 */
 | 
			
		||||
	if (source == XLOG_FROM_ARCHIVE)
 | 
			
		||||
	{
 | 
			
		||||
		Assert(!XLogCtl->InstallXLogFileSegmentActive);
 | 
			
		||||
		KeepFileRestoredFromArchive(path, xlogfname);
 | 
			
		||||
 | 
			
		||||
		/*
 | 
			
		||||
@ -3946,6 +3963,9 @@ PreallocXlogFiles(XLogRecPtr endptr)
 | 
			
		||||
	char		path[MAXPGPATH];
 | 
			
		||||
	uint64		offset;
 | 
			
		||||
 | 
			
		||||
	if (!XLogCtl->InstallXLogFileSegmentActive)
 | 
			
		||||
		return;					/* unlocked check says no */
 | 
			
		||||
 | 
			
		||||
	XLByteToPrevSeg(endptr, _logSegNo, wal_segment_size);
 | 
			
		||||
	offset = XLogSegmentOffset(endptr - 1, wal_segment_size);
 | 
			
		||||
	if (offset >= (uint32) (0.75 * wal_segment_size))
 | 
			
		||||
@ -4227,6 +4247,7 @@ RemoveXlogFile(const char *segname, XLogSegNo recycleSegNo,
 | 
			
		||||
	 */
 | 
			
		||||
	if (wal_recycle &&
 | 
			
		||||
		*endlogSegNo <= recycleSegNo &&
 | 
			
		||||
		XLogCtl->InstallXLogFileSegmentActive &&	/* callee rechecks this */
 | 
			
		||||
		lstat(path, &statbuf) == 0 && S_ISREG(statbuf.st_mode) &&
 | 
			
		||||
		InstallXLogFileSegment(endlogSegNo, path,
 | 
			
		||||
							   true, recycleSegNo))
 | 
			
		||||
@ -4240,7 +4261,7 @@ RemoveXlogFile(const char *segname, XLogSegNo recycleSegNo,
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		/* No need for any more future segments... */
 | 
			
		||||
		/* No need for any more future segments, or recycling failed ... */
 | 
			
		||||
		int			rc;
 | 
			
		||||
 | 
			
		||||
		ereport(DEBUG2,
 | 
			
		||||
@ -5226,6 +5247,7 @@ XLOGShmemInit(void)
 | 
			
		||||
	XLogCtl->XLogCacheBlck = XLOGbuffers - 1;
 | 
			
		||||
	XLogCtl->SharedRecoveryState = RECOVERY_STATE_CRASH;
 | 
			
		||||
	XLogCtl->SharedHotStandbyActive = false;
 | 
			
		||||
	XLogCtl->InstallXLogFileSegmentActive = false;
 | 
			
		||||
	XLogCtl->SharedPromoteIsTriggered = false;
 | 
			
		||||
	XLogCtl->WalWriterSleeping = false;
 | 
			
		||||
 | 
			
		||||
@ -5253,6 +5275,11 @@ BootStrapXLOG(void)
 | 
			
		||||
	struct timeval tv;
 | 
			
		||||
	pg_crc32c	crc;
 | 
			
		||||
 | 
			
		||||
	/* allow ordinary WAL segment creation, like StartupXLOG() would */
 | 
			
		||||
	LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
 | 
			
		||||
	XLogCtl->InstallXLogFileSegmentActive = true;
 | 
			
		||||
	LWLockRelease(ControlFileLock);
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Select a hopefully-unique system identifier code for this installation.
 | 
			
		||||
	 * We use the result of gettimeofday(), including the fractional seconds
 | 
			
		||||
@ -7619,7 +7646,7 @@ StartupXLOG(void)
 | 
			
		||||
	 * the startup checkpoint record. It will trump over the checkpoint and
 | 
			
		||||
	 * subsequent records if it's still alive when we start writing WAL.
 | 
			
		||||
	 */
 | 
			
		||||
	ShutdownWalRcv();
 | 
			
		||||
	XLogShutdownWalRcv();
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Reset unlogged relations to the contents of their INIT fork. This is
 | 
			
		||||
@ -7644,7 +7671,7 @@ StartupXLOG(void)
 | 
			
		||||
	 * recovery, e.g., timeline history file) from archive or pg_wal.
 | 
			
		||||
	 *
 | 
			
		||||
	 * Note that standby mode must be turned off after killing WAL receiver,
 | 
			
		||||
	 * i.e., calling ShutdownWalRcv().
 | 
			
		||||
	 * i.e., calling XLogShutdownWalRcv().
 | 
			
		||||
	 */
 | 
			
		||||
	Assert(!WalRcvStreaming());
 | 
			
		||||
	StandbyMode = false;
 | 
			
		||||
@ -7709,6 +7736,14 @@ StartupXLOG(void)
 | 
			
		||||
	 */
 | 
			
		||||
	oldestActiveXID = PrescanPreparedTransactions(NULL, NULL);
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Allow ordinary WAL segment creation before any exitArchiveRecovery(),
 | 
			
		||||
	 * which sometimes creates a segment, and after the last ReadRecord().
 | 
			
		||||
	 */
 | 
			
		||||
	LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
 | 
			
		||||
	XLogCtl->InstallXLogFileSegmentActive = true;
 | 
			
		||||
	LWLockRelease(ControlFileLock);
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Consider whether we need to assign a new timeline ID.
 | 
			
		||||
	 *
 | 
			
		||||
@ -12378,7 +12413,7 @@ WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool randAccess,
 | 
			
		||||
					 */
 | 
			
		||||
					if (StandbyMode && CheckForStandbyTrigger())
 | 
			
		||||
					{
 | 
			
		||||
						ShutdownWalRcv();
 | 
			
		||||
						XLogShutdownWalRcv();
 | 
			
		||||
						return false;
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
@ -12426,7 +12461,7 @@ WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool randAccess,
 | 
			
		||||
					 * WAL that we restore from archive.
 | 
			
		||||
					 */
 | 
			
		||||
					if (WalRcvStreaming())
 | 
			
		||||
						ShutdownWalRcv();
 | 
			
		||||
						XLogShutdownWalRcv();
 | 
			
		||||
 | 
			
		||||
					/*
 | 
			
		||||
					 * Before we sleep, re-scan for possible new timelines if
 | 
			
		||||
@ -12553,7 +12588,7 @@ WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool randAccess,
 | 
			
		||||
					 */
 | 
			
		||||
					if (pendingWalRcvRestart && !startWalReceiver)
 | 
			
		||||
					{
 | 
			
		||||
						ShutdownWalRcv();
 | 
			
		||||
						XLogShutdownWalRcv();
 | 
			
		||||
 | 
			
		||||
						/*
 | 
			
		||||
						 * Re-scan for possible new timelines if we were
 | 
			
		||||
@ -12603,6 +12638,9 @@ WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool randAccess,
 | 
			
		||||
									 tli, curFileTLI);
 | 
			
		||||
						}
 | 
			
		||||
						curFileTLI = tli;
 | 
			
		||||
						LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
 | 
			
		||||
						XLogCtl->InstallXLogFileSegmentActive = true;
 | 
			
		||||
						LWLockRelease(ControlFileLock);
 | 
			
		||||
						RequestXLogStreaming(tli, ptr, PrimaryConnInfo,
 | 
			
		||||
											 PrimarySlotName,
 | 
			
		||||
											 wal_receiver_create_temp_slot);
 | 
			
		||||
@ -12770,6 +12808,17 @@ StartupRequestWalReceiverRestart(void)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Thin wrapper around ShutdownWalRcv(). */
 | 
			
		||||
static void
 | 
			
		||||
XLogShutdownWalRcv(void)
 | 
			
		||||
{
 | 
			
		||||
	ShutdownWalRcv();
 | 
			
		||||
 | 
			
		||||
	LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
 | 
			
		||||
	XLogCtl->InstallXLogFileSegmentActive = false;
 | 
			
		||||
	LWLockRelease(ControlFileLock);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Determine what log level should be used to report a corrupt WAL record
 | 
			
		||||
 * in the current WAL page, previously read by XLogPageRead().
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user