On 18/11/14 12:57, Simon Riggs wrote:
On 31 October 2014 15:18, Petr Jelinek <p...@2ndquadrant.com> wrote:
Attached is the v2 of the patch with the review comments addressed (see
below).
...
Done, there is now action_at_recovery_target which can be set to either
pause, continue or shutdown, defaulting to pause (which is same as old
behavior of pause_at_recovery_target defaulting to true).
One comment only: I think the actions should be called: pause, promote
and shutdown, since "continue" leads immediately to promotion of the
server.
I'm good with this patch otherwise. Barring objections I will commit tomorrow.
OK, promote works for me as well, I attached patch that changes continue
to promote so you don't have to find and replace everything yourself.
The changed doc wording probably needs to be checked.
--
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..fe42394 100644
--- a/doc/src/sgml/recovery-config.sgml
+++ b/doc/src/sgml/recovery-config.sgml
@@ -289,12 +289,39 @@ restore_command = 'copy "C:\\server\\archivedir\\%f" "%p"' # Windows
</term>
<listitem>
<para>
- Specifies whether recovery should pause when the recovery target
- is reached. The default is true.
- This is intended to allow queries to be executed against the
- database to check if this recovery target is the most desirable
- point for recovery. The paused state can be resumed by using
- <function>pg_xlog_replay_resume()</> (See
+ Alias for action_at_recovery_target, <literal>true</> is same as
+ action_at_recovery_target = <literal>pause</> and <literal>false</>
+ is same as action_at_recovery_target = <literal>promote</>.
+ </para>
+ <para>
+ This setting has no effect if <xref linkend="guc-hot-standby"> is not
+ enabled, or if no recovery target is set.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+
+ <varlistentry id="action-at-recovery-target"
+ xreflabel="action_at_recovery_target">
+ <term><varname>action_at_recovery_target</varname> (<type>enum</type>)
+ <indexterm>
+ <primary><varname>action_at_recovery_target</> recovery parameter</primary>
+ </indexterm>
+ </term>
+ <listitem>
+ <para>
+ Specifies what action should PostgreSQL do once the recovery target is
+ reached. The default is <literal>pause</>, which means recovery will
+ be paused. <literal>promote</> means recovery process will finish and
+ the server will start to accept connections.
+ Finally <literal>shutdown</> will stop the PostgreSQL instance at
+ recovery target.
+ </para>
+ The intended use of <literal>pause</> setting is to allow queries to be
+ executed against the database to check if this recovery target is the
+ most desirable point for recovery. The paused state can be resumed by
+ using <function>pg_xlog_replay_resume()</> (See
<xref linkend="functions-recovery-control-table">), which then
causes recovery to end. If this recovery target is not the
desired stopping point, then shutdown the server, change the
@@ -302,6 +329,20 @@ restore_command = 'copy "C:\\server\\archivedir\\%f" "%p"' # Windows
continue recovery.
</para>
<para>
+ The <literal>shutdown</> setting is useful to have instance ready at
+ exact replay point desired.
+ The instance will still be able to replay more WAL records (and in fact
+ will have to replay WAL records since last checkpoint upon next time it is
+ started).
+ </para>
+ <para>
+ Note that because <filename>recovery.conf</> will not be renamed when
+ <varname>action_at_recovery_target</> is set to <literal>shutdown</>,
+ any subsequent start will end with immediate shutdown unless the
+ configuration is changed or the <filename>recovery.conf</> is removed
+ manually.
+ </para>
+ <para>
This setting has no effect if <xref linkend="guc-hot-standby"> is not
enabled, or if no recovery target is set.
</para>
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 3c9aeae..974e6c1 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -227,7 +227,7 @@ static char *recoveryEndCommand = NULL;
static char *archiveCleanupCommand = NULL;
static RecoveryTargetType recoveryTarget = RECOVERY_TARGET_UNSET;
static bool recoveryTargetInclusive = true;
-static bool recoveryPauseAtTarget = true;
+static RecoveryTargetAction actionAtRecoveryTarget = RECOVERY_TARGET_ACTION_PAUSE;
static TransactionId recoveryTargetXid;
static TimestampTz recoveryTargetTime;
static char *recoveryTargetName;
@@ -5068,6 +5068,9 @@ readRecoveryCommandFile(void)
ConfigVariable *item,
*head = NULL,
*tail = NULL;
+ bool recoveryPauseAtTargetSet = false;
+ bool actionAtRecoveryTargetSet = false;
+
fd = AllocateFile(RECOVERY_COMMAND_FILE, "r");
if (fd == NULL)
@@ -5113,13 +5116,43 @@ readRecoveryCommandFile(void)
}
else if (strcmp(item->name, "pause_at_recovery_target") == 0)
{
+ bool recoveryPauseAtTarget;
+
if (!parse_bool(item->value, &recoveryPauseAtTarget))
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("parameter \"%s\" requires a Boolean value", "pause_at_recovery_target")));
+
ereport(DEBUG2,
(errmsg_internal("pause_at_recovery_target = '%s'",
item->value)));
+
+ actionAtRecoveryTarget = recoveryPauseAtTarget ?
+ RECOVERY_TARGET_ACTION_PAUSE :
+ RECOVERY_TARGET_ACTION_PROMOTE;
+
+ recoveryPauseAtTargetSet = true;
+ }
+ else if (strcmp(item->name, "action_at_recovery_target") == 0)
+ {
+ if (strcmp(item->value, "pause") == 0)
+ actionAtRecoveryTarget = RECOVERY_TARGET_ACTION_PAUSE;
+ else if (strcmp(item->value, "promote") == 0)
+ actionAtRecoveryTarget = RECOVERY_TARGET_ACTION_PROMOTE;
+ else if (strcmp(item->value, "shutdown") == 0)
+ actionAtRecoveryTarget = RECOVERY_TARGET_ACTION_SHUTDOWN;
+ else
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("invalid value for recovery parameter \"%s\"",
+ "action_at_recovery_target"),
+ errhint("The allowed values are \"pause\", \"promote\" and \"shutdown\".")));
+
+ ereport(DEBUG2,
+ (errmsg_internal("action_at_recovery_target = '%s'",
+ item->value)));
+
+ actionAtRecoveryTargetSet = true;
}
else if (strcmp(item->name, "recovery_target_timeline") == 0)
{
@@ -5284,6 +5317,18 @@ readRecoveryCommandFile(void)
RECOVERY_COMMAND_FILE)));
}
+ /*
+ * Check for mutually exclusive parameters
+ */
+ if (recoveryPauseAtTargetSet && actionAtRecoveryTargetSet)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("cannot set both \"%s\" and \"%s\" recovery parameters",
+ "pause_at_recovery_target",
+ "action_at_recovery_target"),
+ errhint("The \"pause_at_recovery_target\" is deprecated.")));
+
+
/* Enable fetching from archive recovery area */
ArchiveRecoveryRequested = true;
@@ -6832,7 +6877,8 @@ StartupXLOG(void)
* end of main redo apply loop
*/
- if (recoveryPauseAtTarget && reachedStopPoint)
+ if (actionAtRecoveryTarget == RECOVERY_TARGET_ACTION_PAUSE &&
+ reachedStopPoint)
{
SetRecoveryPause(true);
recoveryPausesHere();
@@ -6853,6 +6899,25 @@ 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 (actionAtRecoveryTarget == RECOVERY_TARGET_ACTION_SHUTDOWN &&
+ reachedStopPoint)
+ {
+ ereport(LOG, (errmsg("shutting down at recovery target")));
+ /*
+ * 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
diff --git a/src/include/access/xlog.h b/src/include/access/xlog.h
index 0ae110f..7e48138 100644
--- a/src/include/access/xlog.h
+++ b/src/include/access/xlog.h
@@ -179,6 +179,16 @@ typedef enum
RECOVERY_TARGET_IMMEDIATE
} RecoveryTargetType;
+/*
+ * Recovery target action.
+ */
+typedef enum
+{
+ RECOVERY_TARGET_ACTION_PAUSE,
+ RECOVERY_TARGET_ACTION_PROMOTE,
+ RECOVERY_TARGET_ACTION_SHUTDOWN,
+} RecoveryTargetAction;
+
extern XLogRecPtr XactLastRecEnd;
extern bool reachedConsistency;
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers