action_at_recovery_target recovery config option
action_at_recovery_target = pause | promote | shutdown Petr Jelinek Reviewed by Muhammad Asif Naeem, Fujji Masao and Simon Riggs
This commit is contained in:
parent
bb1b8f694a
commit
aedccb1f6f
@ -289,12 +289,39 @@ restore_command = 'copy "C:\\server\\archivedir\\%f" "%p"' # Windows
|
|||||||
</term>
|
</term>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
Specifies whether recovery should pause when the recovery target
|
Alias for action_at_recovery_target, <literal>true</> is same as
|
||||||
is reached. The default is true.
|
action_at_recovery_target = <literal>pause</> and <literal>false</>
|
||||||
This is intended to allow queries to be executed against the
|
is same as action_at_recovery_target = <literal>promote</>.
|
||||||
database to check if this recovery target is the most desirable
|
</para>
|
||||||
point for recovery. The paused state can be resumed by using
|
<para>
|
||||||
<function>pg_xlog_replay_resume()</> (See
|
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
|
<xref linkend="functions-recovery-control-table">), which then
|
||||||
causes recovery to end. If this recovery target is not the
|
causes recovery to end. If this recovery target is not the
|
||||||
desired stopping point, then shutdown the server, change the
|
desired stopping point, then shutdown the server, change the
|
||||||
@ -302,8 +329,23 @@ restore_command = 'copy "C:\\server\\archivedir\\%f" "%p"' # Windows
|
|||||||
continue recovery.
|
continue recovery.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
This setting has no effect if <xref linkend="guc-hot-standby"> is not
|
The <literal>shutdown</> setting is useful to have instance ready at
|
||||||
enabled, or if no recovery target is set.
|
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>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
@ -228,7 +228,7 @@ static char *recoveryEndCommand = NULL;
|
|||||||
static char *archiveCleanupCommand = NULL;
|
static char *archiveCleanupCommand = NULL;
|
||||||
static RecoveryTargetType recoveryTarget = RECOVERY_TARGET_UNSET;
|
static RecoveryTargetType recoveryTarget = RECOVERY_TARGET_UNSET;
|
||||||
static bool recoveryTargetInclusive = true;
|
static bool recoveryTargetInclusive = true;
|
||||||
static bool recoveryPauseAtTarget = true;
|
static RecoveryTargetAction actionAtRecoveryTarget = RECOVERY_TARGET_ACTION_PAUSE;
|
||||||
static TransactionId recoveryTargetXid;
|
static TransactionId recoveryTargetXid;
|
||||||
static TimestampTz recoveryTargetTime;
|
static TimestampTz recoveryTargetTime;
|
||||||
static char *recoveryTargetName;
|
static char *recoveryTargetName;
|
||||||
@ -4647,6 +4647,9 @@ readRecoveryCommandFile(void)
|
|||||||
ConfigVariable *item,
|
ConfigVariable *item,
|
||||||
*head = NULL,
|
*head = NULL,
|
||||||
*tail = NULL;
|
*tail = NULL;
|
||||||
|
bool recoveryPauseAtTargetSet = false;
|
||||||
|
bool actionAtRecoveryTargetSet = false;
|
||||||
|
|
||||||
|
|
||||||
fd = AllocateFile(RECOVERY_COMMAND_FILE, "r");
|
fd = AllocateFile(RECOVERY_COMMAND_FILE, "r");
|
||||||
if (fd == NULL)
|
if (fd == NULL)
|
||||||
@ -4692,13 +4695,43 @@ readRecoveryCommandFile(void)
|
|||||||
}
|
}
|
||||||
else if (strcmp(item->name, "pause_at_recovery_target") == 0)
|
else if (strcmp(item->name, "pause_at_recovery_target") == 0)
|
||||||
{
|
{
|
||||||
|
bool recoveryPauseAtTarget;
|
||||||
|
|
||||||
if (!parse_bool(item->value, &recoveryPauseAtTarget))
|
if (!parse_bool(item->value, &recoveryPauseAtTarget))
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||||
errmsg("parameter \"%s\" requires a Boolean value", "pause_at_recovery_target")));
|
errmsg("parameter \"%s\" requires a Boolean value", "pause_at_recovery_target")));
|
||||||
|
|
||||||
ereport(DEBUG2,
|
ereport(DEBUG2,
|
||||||
(errmsg_internal("pause_at_recovery_target = '%s'",
|
(errmsg_internal("pause_at_recovery_target = '%s'",
|
||||||
item->value)));
|
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)
|
else if (strcmp(item->name, "recovery_target_timeline") == 0)
|
||||||
{
|
{
|
||||||
@ -4863,6 +4896,28 @@ readRecoveryCommandFile(void)
|
|||||||
RECOVERY_COMMAND_FILE)));
|
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 */
|
/* Enable fetching from archive recovery area */
|
||||||
ArchiveRecoveryRequested = true;
|
ArchiveRecoveryRequested = true;
|
||||||
|
|
||||||
@ -6415,10 +6470,37 @@ StartupXLOG(void)
|
|||||||
* end of main redo apply loop
|
* end of main redo apply loop
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (recoveryPauseAtTarget && reachedStopPoint)
|
if (reachedStopPoint)
|
||||||
{
|
{
|
||||||
SetRecoveryPause(true);
|
if (!reachedConsistency)
|
||||||
recoveryPausesHere();
|
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. */
|
/* Allow resource managers to do any required cleanup. */
|
||||||
@ -6436,6 +6518,7 @@ StartupXLOG(void)
|
|||||||
ereport(LOG,
|
ereport(LOG,
|
||||||
(errmsg("last completed transaction was at log time %s",
|
(errmsg("last completed transaction was at log time %s",
|
||||||
timestamptz_to_str(xtime))));
|
timestamptz_to_str(xtime))));
|
||||||
|
|
||||||
InRedo = false;
|
InRedo = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -6496,13 +6579,6 @@ StartupXLOG(void)
|
|||||||
(EndOfLog < minRecoveryPoint ||
|
(EndOfLog < minRecoveryPoint ||
|
||||||
!XLogRecPtrIsInvalid(ControlFile->backupStartPoint)))
|
!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
|
* Ran off end of WAL before reaching end-of-backup WAL record, or
|
||||||
* minRecoveryPoint. That's usually a bad sign, indicating that you
|
* minRecoveryPoint. That's usually a bad sign, indicating that you
|
||||||
|
@ -509,6 +509,7 @@ static void ShmemBackendArrayRemove(Backend *bn);
|
|||||||
/* Macros to check exit status of a child process */
|
/* Macros to check exit status of a child process */
|
||||||
#define EXIT_STATUS_0(st) ((st) == 0)
|
#define EXIT_STATUS_0(st) ((st) == 0)
|
||||||
#define EXIT_STATUS_1(st) (WIFEXITED(st) && WEXITSTATUS(st) == 1)
|
#define EXIT_STATUS_1(st) (WIFEXITED(st) && WEXITSTATUS(st) == 1)
|
||||||
|
#define EXIT_STATUS_3(st) (WIFEXITED(st) && WEXITSTATUS(st) == 3)
|
||||||
|
|
||||||
#ifndef WIN32
|
#ifndef WIN32
|
||||||
/*
|
/*
|
||||||
@ -2555,6 +2556,17 @@ reaper(SIGNAL_ARGS)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (EXIT_STATUS_3(exitstatus))
|
||||||
|
{
|
||||||
|
ereport(LOG,
|
||||||
|
(errmsg("shutdown at recovery target")));
|
||||||
|
Shutdown = SmartShutdown;
|
||||||
|
TerminateChildren(SIGTERM);
|
||||||
|
pmState = PM_WAIT_BACKENDS;
|
||||||
|
/* PostmasterStateMachine logic does the rest */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Unexpected exit of startup process (including FATAL exit)
|
* Unexpected exit of startup process (including FATAL exit)
|
||||||
* during PM_STARTUP is treated as catastrophic. There are no
|
* during PM_STARTUP is treated as catastrophic. There are no
|
||||||
|
@ -214,6 +214,16 @@ typedef struct XLogRecData
|
|||||||
uint32 len; /* length of rmgr data to include */
|
uint32 len; /* length of rmgr data to include */
|
||||||
} XLogRecData;
|
} XLogRecData;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Recovery target action.
|
||||||
|
*/
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
RECOVERY_TARGET_ACTION_PAUSE,
|
||||||
|
RECOVERY_TARGET_ACTION_PROMOTE,
|
||||||
|
RECOVERY_TARGET_ACTION_SHUTDOWN,
|
||||||
|
} RecoveryTargetAction;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Method table for resource managers.
|
* Method table for resource managers.
|
||||||
*
|
*
|
||||||
|
Loading…
x
Reference in New Issue
Block a user