1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-27 12:41:57 +03:00

Minor improvements in backup and recovery:

- create a separate archive_mode GUC, on which archive_command is dependent

- %r option in recovery.conf sends last restartpoint to recovery command

- %r used in pg_standby, updated README

- minor other code cleanup in pg_standby

- doc on Warm Standby now mentions pg_standby and %r

- log_restartpoints recovery option emits LOG message at each restartpoint

- end of recovery now displays last transaction end time, as requested
  by Warren Little; also shown at each restartpoint

- restart archiver if needed to carry away WAL files at shutdown

Simon Riggs
This commit is contained in:
Tom Lane
2007-09-26 22:36:30 +00:00
parent 80963144ad
commit f18dfc4835
12 changed files with 356 additions and 118 deletions

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.281 2007/09/08 20:31:14 tgl Exp $
* $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.282 2007/09/26 22:36:30 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -62,6 +62,7 @@
int CheckPointSegments = 3;
int XLOGbuffers = 8;
int XLogArchiveTimeout = 0;
bool XLogArchiveMode = false;
char *XLogArchiveCommand = NULL;
char *XLOG_sync_method = NULL;
const char XLOG_sync_method_default[] = DEFAULT_SYNC_METHOD_STR;
@ -120,8 +121,10 @@ static char *recoveryRestoreCommand = NULL;
static bool recoveryTarget = false;
static bool recoveryTargetExact = false;
static bool recoveryTargetInclusive = true;
static bool recoveryLogRestartpoints = false;
static TransactionId recoveryTargetXid;
static TimestampTz recoveryTargetTime;
static TimestampTz recoveryLastXTime = 0;
/* if recoveryStopsHere returns true, it saves actual stop xid/time here */
static TransactionId recoveryStopXid;
@ -2388,12 +2391,15 @@ RestoreArchivedFile(char *path, const char *xlogfname,
{
char xlogpath[MAXPGPATH];
char xlogRestoreCmd[MAXPGPATH];
char lastRestartPointFname[MAXPGPATH];
char *dp;
char *endp;
const char *sp;
int rc;
bool signaled;
struct stat stat_buf;
uint32 restartLog;
uint32 restartSeg;
/*
* When doing archive recovery, we always prefer an archived log file even
@ -2466,6 +2472,17 @@ RestoreArchivedFile(char *path, const char *xlogfname,
StrNCpy(dp, xlogfname, endp - dp);
dp += strlen(dp);
break;
case 'r':
/* %r: filename of last restartpoint */
sp++;
XLByteToSeg(ControlFile->checkPointCopy.redo,
restartLog, restartSeg);
XLogFileName(lastRestartPointFname,
ControlFile->checkPointCopy.ThisTimeLineID,
restartLog, restartSeg);
StrNCpy(dp, lastRestartPointFname, endp - dp);
dp += strlen(dp);
break;
case '%':
/* convert %% to a single % */
sp++;
@ -4401,6 +4418,21 @@ readRecoveryCommandFile(void)
ereport(LOG,
(errmsg("recovery_target_inclusive = %s", tok2)));
}
else if (strcmp(tok1, "log_restartpoints") == 0)
{
/*
* does nothing if a recovery_target is not also set
*/
if (strcmp(tok2, "true") == 0)
recoveryLogRestartpoints = true;
else
{
recoveryLogRestartpoints = false;
tok2 = "false";
}
ereport(LOG,
(errmsg("log_restartpoints = %s", tok2)));
}
else
ereport(FATAL,
(errmsg("unrecognized recovery parameter \"%s\"",
@ -4564,10 +4596,6 @@ recoveryStopsHere(XLogRecord *record, bool *includeThis)
uint8 record_info;
TimestampTz recordXtime;
/* Do we have a PITR target at all? */
if (!recoveryTarget)
return false;
/* We only consider stopping at COMMIT or ABORT records */
if (record->xl_rmid != RM_XACT_ID)
return false;
@ -4589,6 +4617,13 @@ recoveryStopsHere(XLogRecord *record, bool *includeThis)
else
return false;
/* Remember the most recent COMMIT/ABORT time for logging purposes */
recoveryLastXTime = recordXtime;
/* Do we have a PITR target at all? */
if (!recoveryTarget)
return false;
if (recoveryTargetExact)
{
/*
@ -5015,6 +5050,10 @@ StartupXLOG(void)
ereport(LOG,
(errmsg("redo done at %X/%X",
ReadRecPtr.xlogid, ReadRecPtr.xrecoff)));
if (recoveryLastXTime)
ereport(LOG,
(errmsg("last completed transaction was at log time %s",
timestamptz_to_str(recoveryLastXTime))));
InRedo = false;
}
else
@ -5922,9 +5961,13 @@ RecoveryRestartPoint(const CheckPoint *checkPoint)
ControlFile->time = time(NULL);
UpdateControlFile();
ereport(DEBUG2,
ereport((recoveryLogRestartpoints ? LOG : DEBUG2),
(errmsg("recovery restart point at %X/%X",
checkPoint->redo.xlogid, checkPoint->redo.xrecoff)));
if (recoveryLastXTime)
ereport((recoveryLogRestartpoints ? LOG : DEBUG2),
(errmsg("last completed transaction was at log time %s",
timestamptz_to_str(recoveryLastXTime))));
}
/*
@ -6285,14 +6328,20 @@ pg_start_backup(PG_FUNCTION_ARGS)
if (!superuser())
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
(errmsg("must be superuser to run a backup"))));
errmsg("must be superuser to run a backup")));
if (!XLogArchivingActive())
ereport(ERROR,
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
(errmsg("WAL archiving is not active"),
(errhint("archive_command must be defined before "
"online backups can be made safely.")))));
errmsg("WAL archiving is not active"),
errhint("archive_mode must be enabled at server start.")));
if (!XLogArchiveCommandSet())
ereport(ERROR,
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
errmsg("WAL archiving is not active"),
errhint("archive_command must be defined before "
"online backups can be made safely.")));
backupidstr = DatumGetCString(DirectFunctionCall1(textout,
PointerGetDatum(backupid)));

View File

@ -19,7 +19,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/postmaster/pgarch.c,v 1.30 2007/08/02 23:39:44 adunstan Exp $
* $PostgreSQL: pgsql/src/backend/postmaster/pgarch.c,v 1.31 2007/09/26 22:36:30 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -314,8 +314,6 @@ pgarch_MainLoop(void)
{
got_SIGHUP = false;
ProcessConfigFile(PGC_SIGHUP);
if (!XLogArchivingActive())
break; /* user wants us to shut down */
}
/* Do what we're here for */
@ -359,6 +357,14 @@ pgarch_ArchiverCopyLoop(void)
{
char xlog[MAX_XFN_CHARS + 1];
if (!XLogArchiveCommandSet())
{
ereport(WARNING,
(errmsg("archive_mode enabled, yet archive_command is not set")));
/* can't do anything if no command ... */
return;
}
/*
* loop through all xlogs with archive_status of .ready and archive
* them...mostly we expect this to be a single file, though it is possible

View File

@ -37,7 +37,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/postmaster/postmaster.c,v 1.541 2007/08/19 01:41:24 adunstan Exp $
* $PostgreSQL: pgsql/src/backend/postmaster/postmaster.c,v 1.542 2007/09/26 22:36:30 tgl Exp $
*
* NOTES
*
@ -1311,8 +1311,12 @@ ServerLoop(void)
start_autovac_launcher = false; /* signal processed */
}
/* If we have lost the archiver, try to start a new one */
if (XLogArchivingActive() && PgArchPID == 0 && pmState == PM_RUN)
/*
* If we have lost the archiver, try to start a new one.
* We do this even if we are shutting down, to allow archiver to
* take care of any remaining WAL files.
*/
if (XLogArchivingActive() && PgArchPID == 0 && pmState >= PM_RUN)
PgArchPID = pgarch_start();
/* If we have lost the stats collector, try to start a new one */
@ -2232,7 +2236,7 @@ reaper(SIGNAL_ARGS)
if (!EXIT_STATUS_0(exitstatus))
LogChildExit(LOG, _("archiver process"),
pid, exitstatus);
if (XLogArchivingActive() && pmState == PM_RUN)
if (XLogArchivingActive() && pmState >= PM_RUN)
PgArchPID = pgarch_start();
continue;
}

View File

@ -10,7 +10,7 @@
* Written by Peter Eisentraut <peter_e@gmx.net>.
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.422 2007/09/25 20:03:38 tgl Exp $
* $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.423 2007/09/26 22:36:30 tgl Exp $
*
*--------------------------------------------------------------------
*/
@ -169,7 +169,7 @@ static const char *assign_backslash_quote(const char *newval, bool doit, GucSour
static const char *assign_timezone_abbreviations(const char *newval, bool doit, GucSource source);
static const char *assign_xmlbinary(const char *newval, bool doit, GucSource source);
static const char *assign_xmloption(const char *newval, bool doit, GucSource source);
static const char *show_archive_command(void);
static bool assign_tcp_keepalives_idle(int newval, bool doit, GucSource source);
static bool assign_tcp_keepalives_interval(int newval, bool doit, GucSource source);
static bool assign_tcp_keepalives_count(int newval, bool doit, GucSource source);
@ -1052,6 +1052,15 @@ static struct config_bool ConfigureNamesBool[] =
false, NULL, NULL
},
{
{"archive_mode", PGC_POSTMASTER, WAL_SETTINGS,
gettext_noop("Allows archiving of WAL files using archive_command."),
NULL
},
&XLogArchiveMode,
false, NULL, NULL
},
{
{"allow_system_table_mods", PGC_POSTMASTER, DEVELOPER_OPTIONS,
gettext_noop("Allows modifications of the structure of system tables."),
@ -1880,7 +1889,7 @@ static struct config_string ConfigureNamesString[] =
NULL
},
&XLogArchiveCommand,
"", NULL, NULL
"", NULL, show_archive_command
},
{
@ -6363,7 +6372,7 @@ GUCArrayDelete(ArrayType *array, const char *name)
/*
* assign_hook subroutines
* assign_hook and show_hook subroutines
*/
static const char *
@ -6972,6 +6981,15 @@ assign_xmloption(const char *newval, bool doit, GucSource source)
return newval;
}
static const char *
show_archive_command(void)
{
if (XLogArchiveMode)
return XLogArchiveCommand;
else
return "(disabled)";
}
static bool
assign_tcp_keepalives_idle(int newval, bool doit, GucSource source)
{

View File

@ -174,6 +174,8 @@
# - Archiving -
#archive_mode = off # allows archiving to be done
# (change requires restart)
#archive_command = '' # command to use to archive a logfile segment
#archive_timeout = 0 # force a logfile segment switch after this
# many seconds; 0 is off

View File

@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/access/xlog.h,v 1.83 2007/09/05 18:10:48 tgl Exp $
* $PostgreSQL: pgsql/src/include/access/xlog.h,v 1.84 2007/09/26 22:36:30 tgl Exp $
*/
#ifndef XLOG_H
#define XLOG_H
@ -138,13 +138,15 @@ extern XLogRecPtr XactLastRecEnd;
/* these variables are GUC parameters related to XLOG */
extern int CheckPointSegments;
extern int XLOGbuffers;
extern bool XLogArchiveMode;
extern char *XLogArchiveCommand;
extern int XLogArchiveTimeout;
extern char *XLOG_sync_method;
extern const char XLOG_sync_method_default[];
extern bool log_checkpoints;
#define XLogArchivingActive() (XLogArchiveCommand[0] != '\0')
#define XLogArchivingActive() (XLogArchiveMode)
#define XLogArchiveCommandSet() (XLogArchiveCommand[0] != '\0')
#ifdef WAL_DEBUG
extern bool XLOG_DEBUG;