Hi,

I recently wanted several times to have slave server prepared at certain point in time to reduce the time it takes for it to replay remaining WALs (say I have pg_basebackup -x on busy db for example). Currently the way to do it is to have pause_at_recovery_target true (default) and wait until pg accepts connection and the shut it down. The issue is that this is ugly, and also there is a chance that somebody else connects and does bad things (tm) before my process does.


So I wrote simple patch that adds option to shut down the cluster once recovery_target is reached. The server will still be able to continue WAL replay if needed later or can be configured to start standalone.


--
 Petr Jelinek                  http://www.2ndQuadrant.com/
 PostgreSQL Development, 24x7 Support, Training & Services
diff --git a/doc/src/sgml/recovery-config.sgml b/doc/src/sgml/recovery-config.sgml
index 0f1ff34..278bbaa 100644
--- a/doc/src/sgml/recovery-config.sgml
+++ b/doc/src/sgml/recovery-config.sgml
@@ -309,6 +309,36 @@ restore_command = 'copy "C:\\server\\archivedir\\%f" "%p"'  # Windows
      </varlistentry>
 
      </variablelist>
+
+     <varlistentry id="shutdown-at-recovery-target"
+                   xreflabel="shutdown_at_recovery_target">
+      <term><varname>shutdown_at_recovery_target</varname> (<type>boolean</type>)
+      <indexterm>
+        <primary><varname>shutdown_at_recovery_target</> recovery parameter</primary>
+      </indexterm>
+      </term>
+      <listitem>
+       <para>
+        Specifies whether postgres should shutdown the once the recovery target
+        is reached. The default is false.
+        This is intended to have instance ready at exact replay point desired.
+        The instance will still be able to replay more WAL records.
+        Note that because reconvery.conf will not be removed if this option is
+        set to true, the above means that unless you change your configuration,
+        any subsequent start will end with immediate shutdown.
+       </para>
+       <para>
+        This setting has no effect if <xref linkend="guc-hot-standby"> is not
+        enabled, or if no recovery target is set.
+       </para>
+       <para>
+        Setting this to true will set <link linkend="pause-at-recovery-target">
+        <varname>pause_at_recovery_target</></link> to false.
+       </para>
+      </listitem>
+     </varlistentry>
+
+     </variablelist>
    </sect1>
 
   <sect1 id="standby-settings">
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 34f2fc0..bbe3987 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -222,6 +222,7 @@ static char *archiveCleanupCommand = NULL;
 static RecoveryTargetType recoveryTarget = RECOVERY_TARGET_UNSET;
 static bool recoveryTargetInclusive = true;
 static bool recoveryPauseAtTarget = true;
+static bool recoveryShutdownAtTarget = false;
 static TransactionId recoveryTargetXid;
 static TimestampTz recoveryTargetTime;
 static char *recoveryTargetName;
@@ -5159,6 +5160,18 @@ readRecoveryCommandFile(void)
 					(errmsg_internal("pause_at_recovery_target = '%s'",
 									 item->value)));
 		}
+		else if (strcmp(item->name, "shutdown_at_recovery_target") == 0)
+		{
+			if (!parse_bool(item->value, &recoveryShutdownAtTarget))
+				ereport(ERROR,
+						(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+						 errmsg("parameter \"%s\" requires a Boolean value", "shutdown_at_recovery_target")));
+			ereport(DEBUG2,
+					(errmsg_internal("shutdown_at_recovery_target = '%s'",
+									 item->value)));
+			if (recoveryShutdownAtTarget)
+				recoveryPauseAtTarget = false;
+		}
 		else if (strcmp(item->name, "recovery_target_timeline") == 0)
 		{
 			rtliGiven = true;
@@ -6907,6 +6920,24 @@ StartupXLOG(void)
 				ereport(LOG,
 					 (errmsg("last completed transaction was at log time %s",
 							 timestamptz_to_str(xtime))));
+
+			/*
+			 * Shutdown here when requested. We need to exit this early because
+			 * we want to be able to continue the WAL replay when started
+			 * the next time.
+			 */
+			if (recoveryShutdownAtTarget && reachedStopPoint)
+			{
+				ereport(LOG, (errmsg("shutting down")));
+				/*
+				 * Note that we exit with status 2 instead of 0 here to force
+				 * postmaster shutdown the whole instance. This produces one
+				 * unnecessary log line, but we don't have better way to
+				 * shutdown postmaster from within single backend.
+				 */
+				proc_exit(2);
+			}
+
 			InRedo = false;
 		}
 		else
-- 
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