Skip to content

Commit aedccb1

Browse files
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
1 parent bb1b8f6 commit aedccb1

File tree

4 files changed

+159
-19
lines changed

4 files changed

+159
-19
lines changed

doc/src/sgml/recovery-config.sgml

Lines changed: 50 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -289,21 +289,63 @@ restore_command = 'copy "C:\\server\\archivedir\\%f" "%p"' # Windows
289289
</term>
290290
<listitem>
291291
<para>
292-
Specifies whether recovery should pause when the recovery target
293-
is reached. The default is true.
294-
This is intended to allow queries to be executed against the
295-
database to check if this recovery target is the most desirable
296-
point for recovery. The paused state can be resumed by using
297-
<function>pg_xlog_replay_resume()</> (See
292+
Alias for action_at_recovery_target, <literal>true</> is same as
293+
action_at_recovery_target = <literal>pause</> and <literal>false</>
294+
is same as action_at_recovery_target = <literal>promote</>.
295+
</para>
296+
<para>
297+
This setting has no effect if <xref linkend="guc-hot-standby"> is not
298+
enabled, or if no recovery target is set.
299+
</para>
300+
</listitem>
301+
</varlistentry>
302+
303+
</variablelist>
304+
305+
<varlistentry id="action-at-recovery-target"
306+
xreflabel="action_at_recovery_target">
307+
<term><varname>action_at_recovery_target</varname> (<type>enum</type>)
308+
<indexterm>
309+
<primary><varname>action_at_recovery_target</> recovery parameter</primary>
310+
</indexterm>
311+
</term>
312+
<listitem>
313+
<para>
314+
Specifies what action the server should take once the recovery target is
315+
reached. The default is <literal>pause</>, which means recovery will
316+
be paused. <literal>promote</> means recovery process will finish and
317+
the server will start to accept connections.
318+
Finally <literal>shutdown</> will stop the server after reaching the
319+
recovery target.
320+
</para>
321+
The intended use of <literal>pause</> setting is to allow queries to be
322+
executed against the database to check if this recovery target is the
323+
most desirable point for recovery. The paused state can be resumed by
324+
using <function>pg_xlog_replay_resume()</> (See
298325
<xref linkend="functions-recovery-control-table">), which then
299326
causes recovery to end. If this recovery target is not the
300327
desired stopping point, then shutdown the server, change the
301328
recovery target settings to a later target and restart to
302329
continue recovery.
303330
</para>
304331
<para>
305-
This setting has no effect if <xref linkend="guc-hot-standby"> is not
306-
enabled, or if no recovery target is set.
332+
The <literal>shutdown</> setting is useful to have instance ready at
333+
exact replay point desired.
334+
The instance will still be able to replay more WAL records (and in fact
335+
will have to replay WAL records since last checkpoint next time it is
336+
started).
337+
</para>
338+
<para>
339+
Note that because <filename>recovery.conf</> will not be renamed when
340+
<varname>action_at_recovery_target</> is set to <literal>shutdown</>,
341+
any subsequent start will end with immediate shutdown unless the
342+
configuration is changed or the <filename>recovery.conf</> is removed
343+
manually.
344+
</para>
345+
<para>
346+
This setting has no effect if no recovery target is set.
347+
If <xref linkend="guc-hot-standby"> is not enabled, a setting of
348+
<literal>pause</> will act the same as <literal>shutdown</>.
307349
</para>
308350
</listitem>
309351
</varlistentry>

src/backend/access/transam/xlog.c

Lines changed: 87 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,7 @@ static char *recoveryEndCommand = NULL;
228228
static char *archiveCleanupCommand = NULL;
229229
static RecoveryTargetType recoveryTarget = RECOVERY_TARGET_UNSET;
230230
static bool recoveryTargetInclusive = true;
231-
static bool recoveryPauseAtTarget = true;
231+
static RecoveryTargetAction actionAtRecoveryTarget = RECOVERY_TARGET_ACTION_PAUSE;
232232
static TransactionId recoveryTargetXid;
233233
static TimestampTz recoveryTargetTime;
234234
static char *recoveryTargetName;
@@ -4647,6 +4647,9 @@ readRecoveryCommandFile(void)
46474647
ConfigVariable *item,
46484648
*head = NULL,
46494649
*tail = NULL;
4650+
bool recoveryPauseAtTargetSet = false;
4651+
bool actionAtRecoveryTargetSet = false;
4652+
46504653

46514654
fd = AllocateFile(RECOVERY_COMMAND_FILE, "r");
46524655
if (fd == NULL)
@@ -4692,13 +4695,43 @@ readRecoveryCommandFile(void)
46924695
}
46934696
else if (strcmp(item->name, "pause_at_recovery_target") == 0)
46944697
{
4698+
bool recoveryPauseAtTarget;
4699+
46954700
if (!parse_bool(item->value, &recoveryPauseAtTarget))
46964701
ereport(ERROR,
46974702
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
46984703
errmsg("parameter \"%s\" requires a Boolean value", "pause_at_recovery_target")));
4704+
46994705
ereport(DEBUG2,
47004706
(errmsg_internal("pause_at_recovery_target = '%s'",
47014707
item->value)));
4708+
4709+
actionAtRecoveryTarget = recoveryPauseAtTarget ?
4710+
RECOVERY_TARGET_ACTION_PAUSE :
4711+
RECOVERY_TARGET_ACTION_PROMOTE;
4712+
4713+
recoveryPauseAtTargetSet = true;
4714+
}
4715+
else if (strcmp(item->name, "action_at_recovery_target") == 0)
4716+
{
4717+
if (strcmp(item->value, "pause") == 0)
4718+
actionAtRecoveryTarget = RECOVERY_TARGET_ACTION_PAUSE;
4719+
else if (strcmp(item->value, "promote") == 0)
4720+
actionAtRecoveryTarget = RECOVERY_TARGET_ACTION_PROMOTE;
4721+
else if (strcmp(item->value, "shutdown") == 0)
4722+
actionAtRecoveryTarget = RECOVERY_TARGET_ACTION_SHUTDOWN;
4723+
else
4724+
ereport(ERROR,
4725+
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4726+
errmsg("invalid value for recovery parameter \"%s\"",
4727+
"action_at_recovery_target"),
4728+
errhint("The allowed values are \"pause\", \"promote\" and \"shutdown\".")));
4729+
4730+
ereport(DEBUG2,
4731+
(errmsg_internal("action_at_recovery_target = '%s'",
4732+
item->value)));
4733+
4734+
actionAtRecoveryTargetSet = true;
47024735
}
47034736
else if (strcmp(item->name, "recovery_target_timeline") == 0)
47044737
{
@@ -4863,6 +4896,28 @@ readRecoveryCommandFile(void)
48634896
RECOVERY_COMMAND_FILE)));
48644897
}
48654898

4899+
/*
4900+
* Check for mutually exclusive parameters
4901+
*/
4902+
if (recoveryPauseAtTargetSet && actionAtRecoveryTargetSet)
4903+
ereport(ERROR,
4904+
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4905+
errmsg("cannot set both \"%s\" and \"%s\" recovery parameters",
4906+
"pause_at_recovery_target",
4907+
"action_at_recovery_target"),
4908+
errhint("The \"pause_at_recovery_target\" is deprecated.")));
4909+
4910+
4911+
/*
4912+
* Override any inconsistent requests. Not that this is a change
4913+
* of behaviour in 9.5; prior to this we simply ignored a request
4914+
* to pause if hot_standby = off, which was surprising behaviour.
4915+
*/
4916+
if (actionAtRecoveryTarget == RECOVERY_TARGET_ACTION_PAUSE &&
4917+
actionAtRecoveryTargetSet &&
4918+
standbyState == STANDBY_DISABLED)
4919+
actionAtRecoveryTarget = RECOVERY_TARGET_ACTION_SHUTDOWN;
4920+
48664921
/* Enable fetching from archive recovery area */
48674922
ArchiveRecoveryRequested = true;
48684923

@@ -6415,10 +6470,37 @@ StartupXLOG(void)
64156470
* end of main redo apply loop
64166471
*/
64176472

6418-
if (recoveryPauseAtTarget && reachedStopPoint)
6473+
if (reachedStopPoint)
64196474
{
6420-
SetRecoveryPause(true);
6421-
recoveryPausesHere();
6475+
if (!reachedConsistency)
6476+
ereport(FATAL,
6477+
(errmsg("requested recovery stop point is before consistent recovery point")));
6478+
6479+
/*
6480+
* This is the last point where we can restart recovery with a
6481+
* new recovery target, if we shutdown and begin again. After
6482+
* this, Resource Managers may choose to do permanent corrective
6483+
* actions at end of recovery.
6484+
*/
6485+
switch (actionAtRecoveryTarget)
6486+
{
6487+
case RECOVERY_TARGET_ACTION_SHUTDOWN:
6488+
/*
6489+
* exit with special return code to request shutdown
6490+
* of postmaster. Log messages issued from
6491+
* postmaster.
6492+
*/
6493+
proc_exit(3);
6494+
6495+
case RECOVERY_TARGET_ACTION_PAUSE:
6496+
SetRecoveryPause(true);
6497+
recoveryPausesHere();
6498+
6499+
/* drop into promote */
6500+
6501+
case RECOVERY_TARGET_ACTION_PROMOTE:
6502+
break;
6503+
}
64226504
}
64236505

64246506
/* Allow resource managers to do any required cleanup. */
@@ -6436,6 +6518,7 @@ StartupXLOG(void)
64366518
ereport(LOG,
64376519
(errmsg("last completed transaction was at log time %s",
64386520
timestamptz_to_str(xtime))));
6521+
64396522
InRedo = false;
64406523
}
64416524
else
@@ -6496,13 +6579,6 @@ StartupXLOG(void)
64966579
(EndOfLog < minRecoveryPoint ||
64976580
!XLogRecPtrIsInvalid(ControlFile->backupStartPoint)))
64986581
{
6499-
if (reachedStopPoint)
6500-
{
6501-
/* stopped because of stop request */
6502-
ereport(FATAL,
6503-
(errmsg("requested recovery stop point is before consistent recovery point")));
6504-
}
6505-
65066582
/*
65076583
* Ran off end of WAL before reaching end-of-backup WAL record, or
65086584
* minRecoveryPoint. That's usually a bad sign, indicating that you

src/backend/postmaster/postmaster.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -509,6 +509,7 @@ static void ShmemBackendArrayRemove(Backend *bn);
509509
/* Macros to check exit status of a child process */
510510
#define EXIT_STATUS_0(st) ((st) == 0)
511511
#define EXIT_STATUS_1(st) (WIFEXITED(st) && WEXITSTATUS(st) == 1)
512+
#define EXIT_STATUS_3(st) (WIFEXITED(st) && WEXITSTATUS(st) == 3)
512513

513514
#ifndef WIN32
514515
/*
@@ -2555,6 +2556,17 @@ reaper(SIGNAL_ARGS)
25552556
continue;
25562557
}
25572558

2559+
if (EXIT_STATUS_3(exitstatus))
2560+
{
2561+
ereport(LOG,
2562+
(errmsg("shutdown at recovery target")));
2563+
Shutdown = SmartShutdown;
2564+
TerminateChildren(SIGTERM);
2565+
pmState = PM_WAIT_BACKENDS;
2566+
/* PostmasterStateMachine logic does the rest */
2567+
continue;
2568+
}
2569+
25582570
/*
25592571
* Unexpected exit of startup process (including FATAL exit)
25602572
* during PM_STARTUP is treated as catastrophic. There are no

src/include/access/xlog_internal.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,16 @@ typedef struct XLogRecData
214214
uint32 len; /* length of rmgr data to include */
215215
} XLogRecData;
216216

217+
/*
218+
* Recovery target action.
219+
*/
220+
typedef enum
221+
{
222+
RECOVERY_TARGET_ACTION_PAUSE,
223+
RECOVERY_TARGET_ACTION_PROMOTE,
224+
RECOVERY_TARGET_ACTION_SHUTDOWN,
225+
} RecoveryTargetAction;
226+
217227
/*
218228
* Method table for resource managers.
219229
*

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy