standby_online_backup_09base-03fpw.patch

application/octet-stream

Filename: standby_online_backup_09base-03fpw.patch
Type: application/octet-stream
Part: 0
Message: Re: Online base backup from the hot-standby

Patch

Same data as JSON: GET /api/v1/attachments/:id/patch the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes. API reference →
Format: context
File+
src/backend/access/transam/xlog.c 75 10
src/backend/postmaster/walwriter.c 12 0
src/include/access/xlog.h 1 0
diff -rcN postgresql_with_9fujii_patch/src/backend/access/transam/xlog.c postgresql_with_patch/src/backend/access/transam/xlog.c
*** postgresql_with_9fujii_patch/src/backend/access/transam/xlog.c	2011-10-06 06:06:19.000000000 +0900
--- postgresql_with_patch/src/backend/access/transam/xlog.c	2011-10-12 06:23:15.000000000 +0900
***************
*** 364,369 ****
--- 364,372 ----
  	bool		exclusiveBackup;
  	int			nonExclusiveBackups;
  	XLogRecPtr	lastBackupStart;
+ 
+ 	/* the startup or the walwriter is logged to its own FPW */
+ 	bool		fullPageWrites;
  } XLogCtlInsert;
  
  /*
***************
*** 453,458 ****
--- 456,464 ----
  	bool		recoveryPause;
  
  	slock_t		info_lck;		/* locks shared variables shown above */
+ 
+ 	/* latest LSN that has recovered a WAL which fpw is 'off' */
+ 	XLogRecPtr	lastFpwDisabledLSN;
  } XLogCtlData;
  
  static XLogCtlData *XLogCtl = NULL;
***************
*** 574,579 ****
--- 580,586 ----
  	int			max_prepared_xacts;
  	int			max_locks_per_xact;
  	int			wal_level;
+ 	bool		fullPageWrites;
  } xl_parameter_change;
  
  /* logs restore point */
***************
*** 612,618 ****
  static void SetLatestXTime(TimestampTz xtime);
  static TimestampTz GetLatestXTime(void);
  static void CheckRequiredParameterValues(void);
- static void XLogReportParameters(void);
  static void LocalSetXLogInsertAllowed(void);
  static void CheckPointGuts(XLogRecPtr checkPointRedo, int flags);
  static void KeepLogSeg(XLogRecPtr recptr, uint32 *logId, uint32 *logSeg);
--- 619,624 ----
***************
*** 763,769 ****
  	 * don't yet have the insert lock, forcePageWrites could change under us,
  	 * but we'll recheck it once we have the lock.
  	 */
! 	doPageWrites = fullPageWrites || Insert->forcePageWrites;
  
  	INIT_CRC32(rdata_crc);
  	len = 0;
--- 769,775 ----
  	 * don't yet have the insert lock, forcePageWrites could change under us,
  	 * but we'll recheck it once we have the lock.
  	 */
! 	doPageWrites = Insert->fullPageWrites || Insert->forcePageWrites;
  
  	INIT_CRC32(rdata_crc);
  	len = 0;
***************
*** 909,915 ****
  	 * just turned off, we could recompute the record without full pages, but
  	 * we choose not to bother.)
  	 */
! 	if (Insert->forcePageWrites && !doPageWrites)
  	{
  		/* Oops, must redo it with full-page data */
  		LWLockRelease(WALInsertLock);
--- 915,921 ----
  	 * just turned off, we could recompute the record without full pages, but
  	 * we choose not to bother.)
  	 */
! 	if ((Insert->fullPageWrites || Insert->forcePageWrites) && !doPageWrites)
  	{
  		/* Oops, must redo it with full-page data */
  		LWLockRelease(WALInsertLock);
***************
*** 6865,6870 ****
--- 6871,6886 ----
  	/* Pre-scan prepared transactions to find out the range of XIDs present */
  	oldestActiveXID = PrescanPreparedTransactions(NULL, NULL);
  
+ 	/*
+ 	 * The startup updates FPW in shaerd-memory after REDO. However, it must
+ 	 * perform before writing the WAL of the CHECKPOINT. The reason is that
+ 	 * it uses a value of fpw in shared-memory when it writes a WAL of its
+ 	 * CHECKPOINT.
+ 	 */
+ 	LWLockAcquire(WALInsertLock, LW_EXCLUSIVE);
+ 	XLogCtl->Insert.fullPageWrites = fullPageWrites;
+ 	LWLockRelease(WALInsertLock);
+ 
  	if (InRecovery)
  	{
  		int			rmid;
***************
*** 6998,7004 ****
  	 * backends to write WAL.
  	 */
  	LocalSetXLogInsertAllowed();
! 	XLogReportParameters();
  
  	/*
  	 * All done.  Allow backends to write WAL.	(Although the bool flag is
--- 7014,7020 ----
  	 * backends to write WAL.
  	 */
  	LocalSetXLogInsertAllowed();
! 	XLogReportParameters(true);
  
  	/*
  	 * All done.  Allow backends to write WAL.	(Although the bool flag is
***************
*** 7860,7865 ****
--- 7876,7885 ----
  	else
  		checkPoint.oldestActiveXid = InvalidTransactionId;
  
+ 	/* Write FPW parameter to WAL at CHECKPOINT */
+ 	if (XLogStandbyInfoActive())
+ 		XLogReportParameters(false);
+ 
  	START_CRIT_SECTION();
  
  	/*
***************
*** 8381,8393 ****
   * Check if any of the GUC parameters that are critical for hot standby
   * have changed, and update the value in pg_control file if necessary.
   */
! static void
! XLogReportParameters(void)
  {
  	if (wal_level != ControlFile->wal_level ||
  		MaxConnections != ControlFile->MaxConnections ||
  		max_prepared_xacts != ControlFile->max_prepared_xacts ||
! 		max_locks_per_xact != ControlFile->max_locks_per_xact)
  	{
  		/*
  		 * The change in number of backend slots doesn't need to be WAL-logged
--- 8401,8423 ----
   * Check if any of the GUC parameters that are critical for hot standby
   * have changed, and update the value in pg_control file if necessary.
   */
! void
! XLogReportParameters(bool fpw_manager)
  {
+ 	bool fpw = fullPageWrites;
+ 
+ 	if (!fpw_manager)
+ 	{
+ 		LWLockAcquire(WALInsertLock, LW_EXCLUSIVE);
+ 		fpw = XLogCtl->Insert.fullPageWrites;
+ 		LWLockRelease(WALInsertLock);
+ 	}
+ 
  	if (wal_level != ControlFile->wal_level ||
  		MaxConnections != ControlFile->MaxConnections ||
  		max_prepared_xacts != ControlFile->max_prepared_xacts ||
! 		max_locks_per_xact != ControlFile->max_locks_per_xact ||
! 		!fpw)
  	{
  		/*
  		 * The change in number of backend slots doesn't need to be WAL-logged
***************
*** 8396,8402 ****
  		 * values in pg_control either if wal_level=minimal, but seems better
  		 * to keep them up-to-date to avoid confusion.
  		 */
! 		if (wal_level != ControlFile->wal_level || XLogIsNeeded())
  		{
  			XLogRecData rdata;
  			xl_parameter_change xlrec;
--- 8426,8432 ----
  		 * values in pg_control either if wal_level=minimal, but seems better
  		 * to keep them up-to-date to avoid confusion.
  		 */
! 		if (wal_level != ControlFile->wal_level || XLogIsNeeded() || !fpw)
  		{
  			XLogRecData rdata;
  			xl_parameter_change xlrec;
***************
*** 8405,8410 ****
--- 8435,8441 ----
  			xlrec.max_prepared_xacts = max_prepared_xacts;
  			xlrec.max_locks_per_xact = max_locks_per_xact;
  			xlrec.wal_level = wal_level;
+ 			xlrec.fullPageWrites = fpw;
  
  			rdata.buffer = InvalidBuffer;
  			rdata.data = (char *) &xlrec;
***************
*** 8420,8425 ****
--- 8451,8464 ----
  		ControlFile->wal_level = wal_level;
  		UpdateControlFile();
  	}
+ 
+ 	/* update own fpw in shared-memory when it has managed fpw */
+ 	if (fpw_manager)
+ 	{
+ 		LWLockAcquire(WALInsertLock, LW_EXCLUSIVE);
+ 		XLogCtl->Insert.fullPageWrites = fullPageWrites;
+ 		LWLockRelease(WALInsertLock);
+ 	}
  }
  
  /*
***************
*** 8604,8609 ****
--- 8643,8651 ----
  	}
  	else if (info == XLOG_PARAMETER_CHANGE)
  	{
+ 		/* use volatile pointer to prevent code rearrangement */
+ 		volatile XLogCtlData *xlogctl = XLogCtl;
+ 
  		xl_parameter_change xlrec;
  
  		/* Update our copy of the parameters in pg_control */
***************
*** 8633,8638 ****
--- 8675,8688 ----
  		UpdateControlFile();
  		LWLockRelease(ControlFileLock);
  
+ 		/* record the LSN when FPW is false on master */
+ 		if (!xlrec.fullPageWrites)
+ 		{
+ 			SpinLockAcquire(&xlogctl->info_lck);
+ 			xlogctl->lastFpwDisabledLSN = lsn;
+ 			SpinLockRelease(&xlogctl->info_lck);
+ 		}
+ 
  		/* Check to see if any changes to max_connections give problems */
  		CheckRequiredParameterValues();
  	}
***************
*** 8711,8721 ****
  			}
  		}
  
! 		appendStringInfo(buf, "parameter change: max_connections=%d max_prepared_xacts=%d max_locks_per_xact=%d wal_level=%s",
  						 xlrec.MaxConnections,
  						 xlrec.max_prepared_xacts,
  						 xlrec.max_locks_per_xact,
! 						 wal_level_str);
  	}
  	else
  		appendStringInfo(buf, "UNKNOWN");
--- 8761,8772 ----
  			}
  		}
  
! 		appendStringInfo(buf, "parameter change: max_connections=%d max_prepared_xacts=%d max_locks_per_xact=%d wal_level=%s full_page_writes=%s",
  						 xlrec.MaxConnections,
  						 xlrec.max_prepared_xacts,
  						 xlrec.max_locks_per_xact,
! 						 wal_level_str,
! 						 xlrec.fullPageWrites ? "true" : "false");
  	}
  	else
  		appendStringInfo(buf, "UNKNOWN");
***************
*** 9089,9094 ****
--- 9140,9153 ----
  				gotUniqueStartpoint = true;
  		} while (!gotUniqueStartpoint);
  
+ 		/*
+ 		 * check whether the master's FPW is 'off' since latest CHECKPOINT.
+ 		 */
+ 		if (recovery_in_progress && XLByteLE(startpoint, XLogCtl->lastFpwDisabledLSN))
+ 			ereport(ERROR,
+ 					(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+ 					 errmsg("full_page_writes on master has been off at some point since latest checkpoint")));
+ 
  		XLByteToSeg(startpoint, _logId, _logSeg);
  		XLogFileName(xlogfilename, ThisTimeLineID, _logId, _logSeg);
  
***************
*** 9372,9377 ****
--- 9431,9442 ----
  						"though pg_start_backup() was executed during recovery"),
  				 errhint("The database backup will not be usable.")));
  
+ 	/* check whether the master's FPW is 'off' since pg_start_backup. */
+ 	if (recovery_in_progress && XLByteLE(startpoint, XLogCtl->lastFpwDisabledLSN))
+ 		ereport(ERROR,
+ 				(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+ 			  errmsg("full_page_writes on master has been off at some point during online backup")));
+ 
  	/*
  	 * During recovery, we don't write an end-of-backup record. We can
  	 * assume that pg_control was backed up just before pg_stop_backup()
diff -rcN postgresql_with_9fujii_patch/src/backend/postmaster/walwriter.c postgresql_with_patch/src/backend/postmaster/walwriter.c
*** postgresql_with_9fujii_patch/src/backend/postmaster/walwriter.c	2011-10-06 06:05:45.000000000 +0900
--- postgresql_with_patch/src/backend/postmaster/walwriter.c	2011-10-12 06:23:15.000000000 +0900
***************
*** 216,221 ****
--- 216,227 ----
  	PG_SETMASK(&UnBlockSig);
  
  	/*
+ 	 * After the startup process, the walwriter manages the FPW. Because
+ 	 * the walwriter may have not received a SIGHUP then, it updates the FPW.
+ 	 */
+ 	XLogReportParameters(true);
+ 
+ 	/*
  	 * Loop forever
  	 */
  	for (;;)
***************
*** 236,241 ****
--- 242,253 ----
  		{
  			got_SIGHUP = false;
  			ProcessConfigFile(PGC_SIGHUP);
+ 
+ 			/*
+ 			 * The walwriter manages the FPW. When the walwriter has received
+ 			 * a SIGHUP, it updates the FPW.
+ 			 */
+ 			XLogReportParameters(true);
  		}
  		if (shutdown_requested)
  		{
diff -rcN postgresql_with_9fujii_patch/src/include/access/xlog.h postgresql_with_patch/src/include/access/xlog.h
*** postgresql_with_9fujii_patch/src/include/access/xlog.h	2011-10-06 06:05:45.000000000 +0900
--- postgresql_with_patch/src/include/access/xlog.h	2011-10-12 06:23:15.000000000 +0900
***************
*** 306,311 ****
--- 306,312 ----
  extern bool CreateRestartPoint(int flags);
  extern void XLogPutNextOid(Oid nextOid);
  extern XLogRecPtr XLogRestorePoint(const char *rpName);
+ extern void XLogReportParameters(bool fpw_manager);
  extern XLogRecPtr GetRedoRecPtr(void);
  extern XLogRecPtr GetInsertRecPtr(void);
  extern XLogRecPtr GetFlushRecPtr(void);