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:
@ -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)));
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
Reference in New Issue
Block a user