From b669f416cee77ef9025b80f9c4201688578447d1 Mon Sep 17 00:00:00 2001
From: Heikki Linnakangas <heikki.linnakangas@iki.fi>
Date: Mon, 11 Feb 2013 22:16:56 +0200
Subject: [PATCH] Fix checkpoint after fast promotion.

The intention was to request a regular online checkpoint immediately after
end of recovery, when performing "fast promotion". However, because the
checkpoint was requested before other backends were allowed to write WAL,
the checkpointer process performed a restartpoint rather than a checkpoint.

Delay the RequestCheckPoint call until after recovery has truly ended, so
that you get a real checkpoint.
---
 src/backend/access/transam/xlog.c | 31 ++++++++++++++++---------------
 1 file changed, 16 insertions(+), 15 deletions(-)

diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 3155238c58d..140f9109a6f 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -4731,6 +4731,7 @@ StartupXLOG(void)
 	DBState		dbstate_at_startup;
 	XLogReaderState *xlogreader;
 	XLogPageReadPrivate private;
+	bool		fast_promoted = false;
 
 	/*
 	 * Read control file and check XLOG status looks valid.
@@ -5781,15 +5782,13 @@ StartupXLOG(void)
 		 * assigning a new TLI, using a shutdown checkpoint allows us to have
 		 * the rule that TLI only changes in shutdown checkpoints, which
 		 * allows some extra error checking in xlog_redo.
+		 *
+		 * In fast promotion, only create a lightweight end-of-recovery record
+		 * instead of a full checkpoint. A checkpoint is requested later, after
+		 * we're fully out of recovery mode and already accepting queries.
 		 */
 		if (bgwriterLaunched)
 		{
-			bool	checkpoint_wait = true;
-
-			/*
-			 * If we've been explicitly promoted with fast option,
-			 * end of recovery without a checkpoint if possible.
-			 */
 			if (fast_promote)
 			{
 				checkPointLoc = ControlFile->prevCheckPoint;
@@ -5802,22 +5801,15 @@ StartupXLOG(void)
 				record = ReadCheckpointRecord(xlogreader, checkPointLoc, 1, false);
 				if (record != NULL)
 				{
-					checkpoint_wait = false;
+					fast_promoted = true;
 					CreateEndOfRecoveryRecord();
 				}
 			}
 
-			/*
-			 * In most cases we will wait for a full checkpoint to complete.
-			 *
-			 * If not, issue a normal, non-immediate checkpoint but don't wait.
-			 */
-			if (checkpoint_wait)
+			if (!fast_promoted)
 				RequestCheckpoint(CHECKPOINT_END_OF_RECOVERY |
 									CHECKPOINT_IMMEDIATE |
 									CHECKPOINT_WAIT);
-			else
-				RequestCheckpoint(0);	/* No flags */
 		}
 		else
 			CreateCheckPoint(CHECKPOINT_END_OF_RECOVERY | CHECKPOINT_IMMEDIATE);
@@ -5925,6 +5917,15 @@ StartupXLOG(void)
 	 * wal sender processes to notice that we've been promoted.
 	 */
 	WalSndWakeup();
+
+	/*
+	 * If this was a fast promotion, request an (online) checkpoint now. This
+	 * isn't required for consistency, but the last restartpoint might be far
+	 * back, and in case of a crash, recovering from it might take a longer
+	 * than is appropriate now that we're not in standby mode anymore.
+	 */
+	if (fast_promoted)
+		RequestCheckpoint(0);
 }
 
 /*
-- 
GitLab