On Fri, Jul 7, 2017 at 3:48 PM, Michael Paquier
<michael.paqu...@gmail.com> wrote:
> On Wed, Jul 5, 2017 at 4:57 PM, Michael Paquier
> <michael.paqu...@gmail.com> wrote:
>> Why not refactoring a bit do_pg_stop_backup() so as the wait phase
>> happens even if a backup is started in recovery? Now wait_for_archive
>> is ignored because no wait is happening and the stop point is directly
>> returned back to the caller. For the wait actually happening, I don't
>> have a better idea than documenting the fact that enforcing manually a
>> segment switch on the primary needs to happen. That's better than
>> having users including WAL in their base backups but not actually
>> having everything they need. And I think that documenting that
>> properly is better than restricting things that should work.
>
> While looking at that in more details, I got surprised by two things:
> 1) No backup history file is generated on a standby during a base backup.
> 2) Because of 1), those files are not archived even if archive_mode = always.
>
> This sounds to me like a missing optimization of archive_mode =
> always, and the following comment block in xlog.c is at least
> incorrect as an archiver can be invoked in recovery:
>      * XXX currently a backup history file is for informational and debug
>      * purposes only. It's not essential for an online backup. Furthermore,
>      * even if it's created, it will not be archived during recovery because
>      * an archiver is not invoked. So it doesn't seem worthwhile to write a
>      * backup history file during recovery.
>
> So I would suggest the following things to address this issue:
> 1) Generate a backup history file for backups taken at recovery as well.
> 2) Archive it if archive_mode = always.
> 3) Wait for both the segment of the stop point and the backup history
> files to be archived before returning back to the caller of
> pg_stop_backup.
>
> It would be nice to get all that addressed in 10. Thoughts?

Yeah, I agree. Attached patch makes it works and deals with the
history file issue.

Regards,

--
Masahiko Sawada
NIPPON TELEGRAPH AND TELEPHONE CORPORATION
NTT Open Source Software Center
diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml
index 3631922..eb47742 100644
--- a/doc/src/sgml/func.sgml
+++ b/doc/src/sgml/func.sgml
@@ -18594,10 +18594,12 @@ postgres=# select pg_start_backup('label_goes_here');
     backup (and not in the data directory).  There is an optional second
     parameter of type <type>boolean</type>.  If false, the <function>pg_stop_backup</>
     will return immediately after the backup is completed without waiting for
-    WAL to be archived.  This behavior is only useful for backup
-    software which independently monitors WAL archiving. Otherwise, WAL
-    required to make the backup consistent might be missing and make the backup
-    useless.
+    WAL to be archived.  This behavior is only useful for backup software
+    which independently monitors WAL archiving. Otherwise, WAL required to
+    make the backup consistent might be missing and make the backup useless.
+    If second parameter is true and on standby, <function>pg_stop_backup</>
+    waits for WAL to be archived without forcibly switching WAL on standby.
+    So enforcing manually a WAL switch on primary needs to happen.
    </para>
 
    <para>
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 5b6cec8..8efb174 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -10875,10 +10875,10 @@ do_pg_stop_backup(char *labelfile, bool waitforarchive, TimeLineID *stoptli_p)
 	 * however.
 	 *
 	 * We don't force a switch to new WAL file and wait for all the required
-	 * files to be archived. This is okay if we use the backup to start the
-	 * standby. But, if it's for an archive recovery, to ensure all the
-	 * required files are available, a user should wait for them to be
-	 * archived, or include them into the backup.
+	 * files to be archived if waitforarchive is false. This is okay if we use
+	 * the backup to start the standby. But, if it's for an archive recovery,
+	 * to ensure all the required files are available, a user should set
+	 * waitforarchive true and wait for them to be archived.
 	 *
 	 * We return the current minimum recovery point as the backup end
 	 * location. Note that it can be greater than the exact backup end
@@ -10886,10 +10886,7 @@ do_pg_stop_backup(char *labelfile, bool waitforarchive, TimeLineID *stoptli_p)
 	 * pg_control. This is harmless for current uses.
 	 *
 	 * XXX currently a backup history file is for informational and debug
-	 * purposes only. It's not essential for an online backup. Furthermore,
-	 * even if it's created, it will not be archived during recovery because
-	 * an archiver is not invoked. So it doesn't seem worthwhile to write a
-	 * backup history file during recovery.
+	 * purposes only. It's not essential for an online backup.
 	 */
 	if (backup_started_in_recovery)
 	{
@@ -10919,39 +10916,40 @@ do_pg_stop_backup(char *labelfile, bool waitforarchive, TimeLineID *stoptli_p)
 		stoptli = ControlFile->minRecoveryPointTLI;
 		LWLockRelease(ControlFileLock);
 
-		if (stoptli_p)
-			*stoptli_p = stoptli;
-		return stoppoint;
+		XLByteToPrevSeg(stoppoint, _logSegNo);
+		XLogFileName(stopxlogfilename, ThisTimeLineID, _logSegNo);
 	}
+	else
+	{
+		/*
+		 * Write the backup-end xlog record
+		 */
+		XLogBeginInsert();
+		XLogRegisterData((char *) (&startpoint), sizeof(startpoint));
+		stoppoint = XLogInsert(RM_XLOG_ID, XLOG_BACKUP_END);
+		stoptli = ThisTimeLineID;
 
-	/*
-	 * Write the backup-end xlog record
-	 */
-	XLogBeginInsert();
-	XLogRegisterData((char *) (&startpoint), sizeof(startpoint));
-	stoppoint = XLogInsert(RM_XLOG_ID, XLOG_BACKUP_END);
-	stoptli = ThisTimeLineID;
-
-	/*
-	 * Force a switch to a new xlog segment file, so that the backup is valid
-	 * as soon as archiver moves out the current segment file.
-	 */
-	RequestXLogSwitch(false);
+		/*
+		 * Force a switch to a new xlog segment file, so that the backup is valid
+		 * as soon as archiver moves out the current segment file.
+		 */
+		RequestXLogSwitch(false);
 
-	XLByteToPrevSeg(stoppoint, _logSegNo);
-	XLogFileName(stopxlogfilename, ThisTimeLineID, _logSegNo);
+		XLByteToPrevSeg(stoppoint, _logSegNo);
+		XLogFileName(stopxlogfilename, ThisTimeLineID, _logSegNo);
 
-	/* Use the log timezone here, not the session timezone */
-	stamp_time = (pg_time_t) time(NULL);
-	pg_strftime(strfbuf, sizeof(strfbuf),
-				"%Y-%m-%d %H:%M:%S %Z",
-				pg_localtime(&stamp_time, log_timezone));
+		/* Use the log timezone here, not the session timezone */
+		stamp_time = (pg_time_t) time(NULL);
+		pg_strftime(strfbuf, sizeof(strfbuf),
+					"%Y-%m-%d %H:%M:%S %Z",
+					pg_localtime(&stamp_time, log_timezone));
+	}
 
 	/*
 	 * Write the backup history file
 	 */
 	XLByteToSeg(startpoint, _logSegNo);
-	BackupHistoryFilePath(histfilepath, ThisTimeLineID, _logSegNo,
+	BackupHistoryFilePath(histfilepath, stoptli, _logSegNo,
 						  (uint32) (startpoint % XLogSegSize));
 	fp = AllocateFile(histfilepath, "w");
 	if (!fp)
@@ -11002,10 +11000,10 @@ do_pg_stop_backup(char *labelfile, bool waitforarchive, TimeLineID *stoptli_p)
 	if (waitforarchive && XLogArchivingActive())
 	{
 		XLByteToPrevSeg(stoppoint, _logSegNo);
-		XLogFileName(lastxlogfilename, ThisTimeLineID, _logSegNo);
+		XLogFileName(lastxlogfilename, stoptli, _logSegNo);
 
 		XLByteToSeg(startpoint, _logSegNo);
-		BackupHistoryFileName(histfilename, ThisTimeLineID, _logSegNo,
+		BackupHistoryFileName(histfilename, stoptli, _logSegNo,
 							  (uint32) (startpoint % XLogSegSize));
 
 		seconds_before_warning = 60;
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to