</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 the server should take 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 server after reaching the
+ 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
continue recovery.
</para>
<para>
- This setting has no effect if <xref linkend="guc-hot-standby"> is not
- enabled, or if no recovery target is set.
+ 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 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 no recovery target is set.
+ If <xref linkend="guc-hot-standby"> is not enabled, a setting of
+ <literal>pause</> will act the same as <literal>shutdown</>.
</para>
</listitem>
</varlistentry>
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;
ConfigVariable *item,
*head = NULL,
*tail = NULL;
+ bool recoveryPauseAtTargetSet = false;
+ bool actionAtRecoveryTargetSet = false;
+
fd = AllocateFile(RECOVERY_COMMAND_FILE, "r");
if (fd == NULL)
}
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)
{
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.")));
+
+
+ /*
+ * Override any inconsistent requests. Not that this is a change
+ * of behaviour in 9.5; prior to this we simply ignored a request
+ * to pause if hot_standby = off, which was surprising behaviour.
+ */
+ if (actionAtRecoveryTarget == RECOVERY_TARGET_ACTION_PAUSE &&
+ actionAtRecoveryTargetSet &&
+ standbyState == STANDBY_DISABLED)
+ actionAtRecoveryTarget = RECOVERY_TARGET_ACTION_SHUTDOWN;
+
/* Enable fetching from archive recovery area */
ArchiveRecoveryRequested = true;
* end of main redo apply loop
*/
- if (recoveryPauseAtTarget && reachedStopPoint)
+ if (reachedStopPoint)
{
- SetRecoveryPause(true);
- recoveryPausesHere();
+ if (!reachedConsistency)
+ ereport(FATAL,
+ (errmsg("requested recovery stop point is before consistent recovery point")));
+
+ /*
+ * This is the last point where we can restart recovery with a
+ * new recovery target, if we shutdown and begin again. After
+ * this, Resource Managers may choose to do permanent corrective
+ * actions at end of recovery.
+ */
+ switch (actionAtRecoveryTarget)
+ {
+ case RECOVERY_TARGET_ACTION_SHUTDOWN:
+ /*
+ * exit with special return code to request shutdown
+ * of postmaster. Log messages issued from
+ * postmaster.
+ */
+ proc_exit(3);
+
+ case RECOVERY_TARGET_ACTION_PAUSE:
+ SetRecoveryPause(true);
+ recoveryPausesHere();
+
+ /* drop into promote */
+
+ case RECOVERY_TARGET_ACTION_PROMOTE:
+ break;
+ }
}
/* Allow resource managers to do any required cleanup. */
ereport(LOG,
(errmsg("last completed transaction was at log time %s",
timestamptz_to_str(xtime))));
+
InRedo = false;
}
else
(EndOfLog < minRecoveryPoint ||
!XLogRecPtrIsInvalid(ControlFile->backupStartPoint)))
{
- if (reachedStopPoint)
- {
- /* stopped because of stop request */
- ereport(FATAL,
- (errmsg("requested recovery stop point is before consistent recovery point")));
- }
-
/*
* Ran off end of WAL before reaching end-of-backup WAL record, or
* minRecoveryPoint. That's usually a bad sign, indicating that you