mirror of
https://github.com/postgres/postgres.git
synced 2025-04-21 12:05:57 +03:00
Add restartpoint_command option to recovery.conf. Fix bug in %r handling
in recovery_end_command, it always came out as 0 because InRedo was cleared before recovery_end_command was executed. Also, always take ControlFileLock when reading checkpoint location for %r. The recovery_end_command bug and the missing locking was present in 8.4 as well, that part of this patch will be backported separately.
This commit is contained in:
parent
6407fa996a
commit
c21ac0b58e
@ -1,4 +1,4 @@
|
|||||||
<!-- $PostgreSQL: pgsql/doc/src/sgml/recovery-config.sgml,v 2.2 2010/02/25 09:32:19 heikki Exp $ -->
|
<!-- $PostgreSQL: pgsql/doc/src/sgml/recovery-config.sgml,v 2.3 2010/03/18 09:17:18 heikki Exp $ -->
|
||||||
|
|
||||||
<chapter Id="recovery-config">
|
<chapter Id="recovery-config">
|
||||||
<title>Recovery Configuration</title>
|
<title>Recovery Configuration</title>
|
||||||
@ -59,14 +59,15 @@ restore_command = 'copy "C:\\server\\archivedir\\%f" "%p"' # Windows
|
|||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry id="recovery-end-command" xreflabel="recovery_end_command">
|
<varlistentry id="restartpoint-command" xreflabel="restartpoint_command">
|
||||||
<term><varname>recovery_end_command</varname> (<type>string</type>)</term>
|
<term><varname>restartpoint_command</varname> (<type>string</type>)</term>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
This parameter specifies a shell command that will be executed once only
|
This parameter specifies a shell command that will be executed at
|
||||||
at the end of recovery. This parameter is optional. The purpose of the
|
every restartpoint. This parameter is optional. The purpose of the
|
||||||
<varname>recovery_end_command</> is to provide a mechanism for cleanup
|
<varname>restartpoint_command</> is to provide a mechanism for cleaning
|
||||||
following replication or recovery.
|
up old archived WAL files that are no longer needed by the standby
|
||||||
|
server.
|
||||||
Any <literal>%r</> is replaced by the name of the file
|
Any <literal>%r</> is replaced by the name of the file
|
||||||
containing the last valid restart point. That is the earliest file that
|
containing the last valid restart point. That is the earliest file that
|
||||||
must be kept to allow a restore to be restartable, so this information
|
must be kept to allow a restore to be restartable, so this information
|
||||||
@ -77,6 +78,24 @@ restore_command = 'copy "C:\\server\\archivedir\\%f" "%p"' # Windows
|
|||||||
Write <literal>%%</> to embed an actual <literal>%</> character
|
Write <literal>%%</> to embed an actual <literal>%</> character
|
||||||
in the command.
|
in the command.
|
||||||
</para>
|
</para>
|
||||||
|
<para>
|
||||||
|
If the command returns a non-zero exit status then a WARNING log
|
||||||
|
message will be written.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry id="recovery-end-command" xreflabel="recovery_end_command">
|
||||||
|
<term><varname>recovery_end_command</varname> (<type>string</type>)</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
This parameter specifies a shell command that will be executed once only
|
||||||
|
at the end of recovery. This parameter is optional. The purpose of the
|
||||||
|
<varname>recovery_end_command</> is to provide a mechanism for cleanup
|
||||||
|
following replication or recovery.
|
||||||
|
Any <literal>%r</> is replaced by the name of the file containing the
|
||||||
|
last valid restart point, like in <xref linkend="restartpoint-command">.
|
||||||
|
</para>
|
||||||
<para>
|
<para>
|
||||||
If the command returns a non-zero exit status then a WARNING log
|
If the command returns a non-zero exit status then a WARNING log
|
||||||
message will be written and the database will proceed to start up
|
message will be written and the database will proceed to start up
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.381 2010/03/15 18:49:17 sriggs Exp $
|
* $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.382 2010/03/18 09:17:18 heikki Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -171,6 +171,7 @@ static bool restoredFromArchive = false;
|
|||||||
/* options taken from recovery.conf for archive recovery */
|
/* options taken from recovery.conf for archive recovery */
|
||||||
static char *recoveryRestoreCommand = NULL;
|
static char *recoveryRestoreCommand = NULL;
|
||||||
static char *recoveryEndCommand = NULL;
|
static char *recoveryEndCommand = NULL;
|
||||||
|
static char *restartPointCommand = NULL;
|
||||||
static bool recoveryTarget = false;
|
static bool recoveryTarget = false;
|
||||||
static bool recoveryTargetExact = false;
|
static bool recoveryTargetExact = false;
|
||||||
static bool recoveryTargetInclusive = true;
|
static bool recoveryTargetInclusive = true;
|
||||||
@ -370,6 +371,11 @@ typedef struct XLogCtlData
|
|||||||
int XLogCacheBlck; /* highest allocated xlog buffer index */
|
int XLogCacheBlck; /* highest allocated xlog buffer index */
|
||||||
TimeLineID ThisTimeLineID;
|
TimeLineID ThisTimeLineID;
|
||||||
TimeLineID RecoveryTargetTLI;
|
TimeLineID RecoveryTargetTLI;
|
||||||
|
/*
|
||||||
|
* restartPointCommand is read from recovery.conf but needs to be in
|
||||||
|
* shared memory so that the bgwriter process can access it.
|
||||||
|
*/
|
||||||
|
char restartPointCommand[MAXPGPATH];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* SharedRecoveryInProgress indicates if we're still in crash or archive
|
* SharedRecoveryInProgress indicates if we're still in crash or archive
|
||||||
@ -520,7 +526,8 @@ static bool XLogPageRead(XLogRecPtr *RecPtr, int emode, bool fetching_ckpt,
|
|||||||
static void XLogFileClose(void);
|
static void XLogFileClose(void);
|
||||||
static bool RestoreArchivedFile(char *path, const char *xlogfname,
|
static bool RestoreArchivedFile(char *path, const char *xlogfname,
|
||||||
const char *recovername, off_t expectedSize);
|
const char *recovername, off_t expectedSize);
|
||||||
static void ExecuteRecoveryEndCommand(void);
|
static void ExecuteRecoveryCommand(char *command, char *commandName,
|
||||||
|
bool failOnerror);
|
||||||
static void PreallocXlogFiles(XLogRecPtr endptr);
|
static void PreallocXlogFiles(XLogRecPtr endptr);
|
||||||
static void RemoveOldXlogFiles(uint32 log, uint32 seg, XLogRecPtr endptr);
|
static void RemoveOldXlogFiles(uint32 log, uint32 seg, XLogRecPtr endptr);
|
||||||
static void ValidateXLOGDirectoryStructure(void);
|
static void ValidateXLOGDirectoryStructure(void);
|
||||||
@ -2990,12 +2997,19 @@ not_available:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Attempt to execute the recovery_end_command.
|
* Attempt to execute an external shell command during recovery.
|
||||||
|
*
|
||||||
|
* 'command' is the shell command to be executed, 'commandName' is a
|
||||||
|
* human-readable name describing the command emitted in the logs. If
|
||||||
|
* 'failonSignal' is true and the command is killed by a signal, a FATAL
|
||||||
|
* error is thrown. Otherwise a WARNING is emitted.
|
||||||
|
*
|
||||||
|
* This is currently used for restore_end_command and restartpoint_command.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
ExecuteRecoveryEndCommand(void)
|
ExecuteRecoveryCommand(char *command, char *commandName, bool failOnSignal)
|
||||||
{
|
{
|
||||||
char xlogRecoveryEndCmd[MAXPGPATH];
|
char xlogRecoveryCmd[MAXPGPATH];
|
||||||
char lastRestartPointFname[MAXPGPATH];
|
char lastRestartPointFname[MAXPGPATH];
|
||||||
char *dp;
|
char *dp;
|
||||||
char *endp;
|
char *endp;
|
||||||
@ -3005,43 +3019,29 @@ ExecuteRecoveryEndCommand(void)
|
|||||||
uint32 restartLog;
|
uint32 restartLog;
|
||||||
uint32 restartSeg;
|
uint32 restartSeg;
|
||||||
|
|
||||||
Assert(recoveryEndCommand);
|
Assert(command && commandName);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Calculate the archive file cutoff point for use during log shipping
|
* Calculate the archive file cutoff point for use during log shipping
|
||||||
* replication. All files earlier than this point can be deleted from the
|
* replication. All files earlier than this point can be deleted from the
|
||||||
* archive, though there is no requirement to do so.
|
* archive, though there is no requirement to do so.
|
||||||
*
|
|
||||||
* We initialise this with the filename of an InvalidXLogRecPtr, which
|
|
||||||
* will prevent the deletion of any WAL files from the archive because of
|
|
||||||
* the alphabetic sorting property of WAL filenames.
|
|
||||||
*
|
|
||||||
* Once we have successfully located the redo pointer of the checkpoint
|
|
||||||
* from which we start recovery we never request a file prior to the redo
|
|
||||||
* pointer of the last restartpoint. When redo begins we know that we have
|
|
||||||
* successfully located it, so there is no need for additional status
|
|
||||||
* flags to signify the point when we can begin deleting WAL files from
|
|
||||||
* the archive.
|
|
||||||
*/
|
*/
|
||||||
if (InRedo)
|
LWLockAcquire(ControlFileLock, LW_SHARED);
|
||||||
{
|
XLByteToSeg(ControlFile->checkPointCopy.redo,
|
||||||
XLByteToSeg(ControlFile->checkPointCopy.redo,
|
restartLog, restartSeg);
|
||||||
restartLog, restartSeg);
|
XLogFileName(lastRestartPointFname,
|
||||||
XLogFileName(lastRestartPointFname,
|
ControlFile->checkPointCopy.ThisTimeLineID,
|
||||||
ControlFile->checkPointCopy.ThisTimeLineID,
|
restartLog, restartSeg);
|
||||||
restartLog, restartSeg);
|
LWLockRelease(ControlFileLock);
|
||||||
}
|
|
||||||
else
|
|
||||||
XLogFileName(lastRestartPointFname, 0, 0, 0);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* construct the command to be executed
|
* construct the command to be executed
|
||||||
*/
|
*/
|
||||||
dp = xlogRecoveryEndCmd;
|
dp = xlogRecoveryCmd;
|
||||||
endp = xlogRecoveryEndCmd + MAXPGPATH - 1;
|
endp = xlogRecoveryCmd + MAXPGPATH - 1;
|
||||||
*endp = '\0';
|
*endp = '\0';
|
||||||
|
|
||||||
for (sp = recoveryEndCommand; *sp; sp++)
|
for (sp = command; *sp; sp++)
|
||||||
{
|
{
|
||||||
if (*sp == '%')
|
if (*sp == '%')
|
||||||
{
|
{
|
||||||
@ -3075,13 +3075,12 @@ ExecuteRecoveryEndCommand(void)
|
|||||||
*dp = '\0';
|
*dp = '\0';
|
||||||
|
|
||||||
ereport(DEBUG3,
|
ereport(DEBUG3,
|
||||||
(errmsg_internal("executing recovery end command \"%s\"",
|
(errmsg_internal("executing %s \"%s\"", commandName, command)));
|
||||||
xlogRecoveryEndCmd)));
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* execute the constructed command
|
* execute the constructed command
|
||||||
*/
|
*/
|
||||||
rc = system(xlogRecoveryEndCmd);
|
rc = system(xlogRecoveryCmd);
|
||||||
if (rc != 0)
|
if (rc != 0)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@ -3091,9 +3090,13 @@ ExecuteRecoveryEndCommand(void)
|
|||||||
*/
|
*/
|
||||||
signaled = WIFSIGNALED(rc) || WEXITSTATUS(rc) > 125;
|
signaled = WIFSIGNALED(rc) || WEXITSTATUS(rc) > 125;
|
||||||
|
|
||||||
ereport(signaled ? FATAL : WARNING,
|
/*
|
||||||
(errmsg("recovery_end_command \"%s\": return code %d",
|
* translator: First %s represents a recovery.conf parameter name like
|
||||||
xlogRecoveryEndCmd, rc)));
|
* "recovery_end_command", and the 2nd is the value of that parameter.
|
||||||
|
*/
|
||||||
|
ereport((signaled && failOnSignal) ? FATAL : WARNING,
|
||||||
|
(errmsg("%s \"%s\": return code %d", commandName,
|
||||||
|
command, rc)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4936,6 +4939,13 @@ readRecoveryCommandFile(void)
|
|||||||
(errmsg("recovery_end_command = '%s'",
|
(errmsg("recovery_end_command = '%s'",
|
||||||
recoveryEndCommand)));
|
recoveryEndCommand)));
|
||||||
}
|
}
|
||||||
|
else if (strcmp(tok1, "restartpoint_command") == 0)
|
||||||
|
{
|
||||||
|
restartPointCommand = pstrdup(tok2);
|
||||||
|
ereport(DEBUG2,
|
||||||
|
(errmsg("restartpoint_command = '%s'",
|
||||||
|
restartPointCommand)));
|
||||||
|
}
|
||||||
else if (strcmp(tok1, "recovery_target_timeline") == 0)
|
else if (strcmp(tok1, "recovery_target_timeline") == 0)
|
||||||
{
|
{
|
||||||
rtliGiven = true;
|
rtliGiven = true;
|
||||||
@ -5505,8 +5515,14 @@ StartupXLOG(void)
|
|||||||
recoveryTargetTLI,
|
recoveryTargetTLI,
|
||||||
ControlFile->checkPointCopy.ThisTimeLineID)));
|
ControlFile->checkPointCopy.ThisTimeLineID)));
|
||||||
|
|
||||||
/* Save the selected recovery target timeline ID in shared memory */
|
/*
|
||||||
|
* Save the selected recovery target timeline ID and restartpoint_command
|
||||||
|
* in shared memory so that other processes can see them
|
||||||
|
*/
|
||||||
XLogCtl->RecoveryTargetTLI = recoveryTargetTLI;
|
XLogCtl->RecoveryTargetTLI = recoveryTargetTLI;
|
||||||
|
strncpy(XLogCtl->restartPointCommand,
|
||||||
|
restartPointCommand ? restartPointCommand : "",
|
||||||
|
sizeof(XLogCtl->restartPointCommand));
|
||||||
|
|
||||||
if (read_backup_label(&checkPointLoc))
|
if (read_backup_label(&checkPointLoc))
|
||||||
{
|
{
|
||||||
@ -6129,7 +6145,9 @@ StartupXLOG(void)
|
|||||||
* And finally, execute the recovery_end_command, if any.
|
* And finally, execute the recovery_end_command, if any.
|
||||||
*/
|
*/
|
||||||
if (recoveryEndCommand)
|
if (recoveryEndCommand)
|
||||||
ExecuteRecoveryEndCommand();
|
ExecuteRecoveryCommand(recoveryEndCommand,
|
||||||
|
"recovery_end_command",
|
||||||
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -7318,6 +7336,15 @@ CreateRestartPoint(int flags)
|
|||||||
timestamptz_to_str(GetLatestXLogTime()))));
|
timestamptz_to_str(GetLatestXLogTime()))));
|
||||||
|
|
||||||
LWLockRelease(CheckpointLock);
|
LWLockRelease(CheckpointLock);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Finally, execute restartpoint_command, if any.
|
||||||
|
*/
|
||||||
|
if (XLogCtl->restartPointCommand[0])
|
||||||
|
ExecuteRecoveryCommand(XLogCtl->restartPointCommand,
|
||||||
|
"restartpoint_command",
|
||||||
|
false);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user