Prevent shutdown in normal mode if online backup is running, and

have pg_ctl warn about this.

Cancel running online backups (by renaming the backup_label file,
thus rendering the backup useless) when shutting down in fast mode.

Laurenz Albe
This commit is contained in:
Magnus Hagander 2008-04-23 13:44:59 +00:00
parent cf23b75b4d
commit c979a1fefa
6 changed files with 115 additions and 14 deletions

View File

@ -1,5 +1,5 @@
<!--
$PostgreSQL: pgsql/doc/src/sgml/ref/pg_ctl-ref.sgml,v 1.44 2007/11/10 21:48:51 momjian Exp $
$PostgreSQL: pgsql/doc/src/sgml/ref/pg_ctl-ref.sgml,v 1.45 2008/04/23 13:44:58 mha Exp $
PostgreSQL documentation
-->
@ -133,9 +133,10 @@ PostgreSQL documentation
In <option>stop</option> mode, the server that is running in
the specified data directory is shut down. Three different
shutdown methods can be selected with the <option>-m</option>
option: <quote>Smart</quote> mode waits for all the clients to
disconnect. This is the default. <quote>Fast</quote> mode does
not wait for clients to disconnect. All active transactions are
option: <quote>Smart</quote> mode waits for online backup mode
to finish and all the clients to disconnect. This is the default.
<quote>Fast</quote> mode does not wait for clients to disconnect and
will terminate an online backup in progress. All active transactions are
rolled back and clients are forcibly disconnected, then the
server is shut down. <quote>Immediate</quote> mode will abort
all server processes without a clean shutdown. This will lead to

View File

@ -1,4 +1,4 @@
<!-- $PostgreSQL: pgsql/doc/src/sgml/runtime.sgml,v 1.414 2008/04/17 20:56:41 momjian Exp $ -->
<!-- $PostgreSQL: pgsql/doc/src/sgml/runtime.sgml,v 1.415 2008/04/23 13:44:58 mha Exp $ -->
<chapter Id="runtime">
<title>Operating System Environment</title>
@ -1307,6 +1307,7 @@ sysctl -w vm.overcommit_memory=2
<listitem>
<para>
After receiving <systemitem>SIGTERM</systemitem>, the server
waits until online backup mode is no longer active. It then
disallows new connections, but lets existing sessions end their
work normally. It shuts down only after all of the sessions
terminate normally. This is the <firstterm>Smart
@ -1322,7 +1323,9 @@ sysctl -w vm.overcommit_memory=2
The server disallows new connections and sends all existing
server processes <systemitem>SIGTERM</systemitem>, which will cause them
to abort their current transactions and exit promptly. It then
waits for the server processes to exit and finally shuts down. This is the
waits for the server processes to exit and finally shuts down.
If the server is in online backup mode, backup mode will be
terminated, rendering the backup useless. This is the
<firstterm>Fast Shutdown</firstterm>.
</para>
</listitem>

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.298 2008/04/21 00:26:44 tgl Exp $
* $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.299 2008/04/23 13:44:58 mha Exp $
*
*-------------------------------------------------------------------------
*/
@ -6577,6 +6577,7 @@ pg_start_backup_callback(int code, Datum arg)
* create a backup history file in pg_xlog (whence it will immediately be
* archived). The backup history file contains the same info found in
* the label file, plus the backup-end time and WAL location.
* Note: different from CancelBackup which just cancels online backup mode.
*/
Datum
pg_stop_backup(PG_FUNCTION_ARGS)
@ -7063,3 +7064,52 @@ rm_redo_error_callback(void *arg)
pfree(buf.data);
}
/*
* BackupInProgress: check if online backup mode is active
*
* This is done by checking for existence of the "backup_label" file.
*/
bool
BackupInProgress(void)
{
struct stat stat_buf;
return (stat(BACKUP_LABEL_FILE, &stat_buf) == 0);
}
/*
* CancelBackup: rename the "backup_label" file to cancel backup mode
*
* If the "backup_label" file exists, it will be renamed to "backup_label.old".
* Note that this will render an online backup in progress useless.
* To correctly finish an online backup, pg_stop_backup must be called.
*/
void
CancelBackup(void)
{
struct stat stat_buf;
/* if the file is not there, return */
if (stat(BACKUP_LABEL_FILE, &stat_buf) < 0)
return;
/* remove leftover file from previously cancelled backup if it exists */
unlink(BACKUP_LABEL_OLD);
if (rename(BACKUP_LABEL_FILE, BACKUP_LABEL_OLD) == 0)
{
ereport(LOG,
(errmsg("online backup mode cancelled"),
errdetail("\"%s\" renamed to \"%s\"",
BACKUP_LABEL_FILE, BACKUP_LABEL_OLD)));
}
else
{
ereport(WARNING,
(errcode_for_file_access(),
errmsg("could not rename \"%s\" to \"%s\", backup mode not cancelled: %m",
BACKUP_LABEL_FILE, BACKUP_LABEL_OLD)));
}
}

View File

@ -37,7 +37,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/postmaster/postmaster.c,v 1.554 2008/03/31 02:43:14 tgl Exp $
* $PostgreSQL: pgsql/src/backend/postmaster/postmaster.c,v 1.555 2008/04/23 13:44:59 mha Exp $
*
* NOTES
*
@ -253,6 +253,7 @@ typedef enum
PM_INIT, /* postmaster starting */
PM_STARTUP, /* waiting for startup subprocess */
PM_RUN, /* normal "database is alive" state */
PM_WAIT_BACKUP, /* waiting for online backup mode to end */
PM_WAIT_BACKENDS, /* waiting for live backends to exit */
PM_SHUTDOWN, /* waiting for bgwriter to do shutdown ckpt */
PM_SHUTDOWN_2, /* waiting for archiver to finish */
@ -1724,8 +1725,12 @@ processCancelRequest(Port *port, void *pkt)
static enum CAC_state
canAcceptConnections(void)
{
/* Can't start backends when in startup/shutdown/recovery state. */
if (pmState != PM_RUN)
/*
* Can't start backends when in startup/shutdown/recovery state.
* In state PM_WAIT_BACKUP we must allow connections so that
* a superuser can end online backup mode.
*/
if ((pmState != PM_RUN) && (pmState != PM_WAIT_BACKUP))
{
if (Shutdown > NoShutdown)
return CAC_SHUTDOWN; /* shutdown is pending */
@ -1965,11 +1970,12 @@ pmdie(SIGNAL_ARGS)
/* and the walwriter too */
if (WalWriterPID != 0)
signal_child(WalWriterPID, SIGTERM);
pmState = PM_WAIT_BACKENDS;
pmState = PM_WAIT_BACKUP;
}
/*
* Now wait for backends to exit. If there are none,
* Now wait for online backup mode to end and
* backends to exit. If that is already the case,
* PostmasterStateMachine will take the next step.
*/
PostmasterStateMachine();
@ -2011,6 +2017,13 @@ pmdie(SIGNAL_ARGS)
* PostmasterStateMachine will take the next step.
*/
PostmasterStateMachine();
/*
* Terminate backup mode to avoid recovery after a
* clean fast shutdown.
*/
CancelBackup();
break;
case SIGQUIT:
@ -2552,6 +2565,20 @@ LogChildExit(int lev, const char *procname, int pid, int exitstatus)
static void
PostmasterStateMachine(void)
{
if (pmState == PM_WAIT_BACKUP)
{
/*
* PM_WAIT_BACKUP state ends when online backup mode is no longer
* active. In this state canAcceptConnections() will still allow
* client connections, which is necessary because a superuser
* has to call pg_stop_backup() to end online backup mode.
*/
if (!BackupInProgress())
{
pmState = PM_WAIT_BACKENDS;
}
}
/*
* If we are in a state-machine state that implies waiting for backends to
* exit, see if they're all gone, and change state if so.

View File

@ -4,7 +4,7 @@
*
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
*
* $PostgreSQL: pgsql/src/bin/pg_ctl/pg_ctl.c,v 1.96 2008/02/29 23:31:20 adunstan Exp $
* $PostgreSQL: pgsql/src/bin/pg_ctl/pg_ctl.c,v 1.97 2008/04/23 13:44:59 mha Exp $
*
*-------------------------------------------------------------------------
*/
@ -144,6 +144,7 @@ static char def_postopts_file[MAXPGPATH];
static char postopts_file[MAXPGPATH];
static char pid_file[MAXPGPATH];
static char conf_file[MAXPGPATH];
static char backup_file[MAXPGPATH];
#if defined(HAVE_GETRLIMIT) && defined(RLIMIT_CORE)
static void unlimit_core_size(void);
@ -731,6 +732,7 @@ do_stop(void)
{
int cnt;
pgpid_t pid;
struct stat statbuf;
pid = get_pgpid();
@ -763,6 +765,12 @@ do_stop(void)
}
else
{
if ((shutdown_mode == SMART_MODE) && (stat(backup_file, &statbuf) == 0))
{
print_msg(_("WARNING: online backup mode is active; must be ended\n"
" with pg_stop_backup() for shutdown to complete\n\n"));
}
print_msg(_("waiting for server to shut down..."));
for (cnt = 0; cnt < wait_seconds; cnt++)
@ -799,6 +807,7 @@ do_restart(void)
{
int cnt;
pgpid_t pid;
struct stat statbuf;
pid = get_pgpid();
@ -833,6 +842,12 @@ do_restart(void)
exit(1);
}
if ((shutdown_mode == SMART_MODE) && (stat(backup_file, &statbuf) == 0))
{
print_msg(_("WARNING: online backup mode is active; must be ended\n"
" with pg_stop_backup() for shutdown to complete\n\n"));
}
print_msg(_("waiting for server to shut down..."));
/* always wait for restart */
@ -1883,6 +1898,7 @@ main(int argc, char **argv)
snprintf(postopts_file, MAXPGPATH, "%s/postmaster.opts", pg_data);
snprintf(pid_file, MAXPGPATH, "%s/postmaster.pid", pg_data);
snprintf(conf_file, MAXPGPATH, "%s/postgresql.conf", pg_data);
snprintf(backup_file, MAXPGPATH, "%s/backup_label", pg_data);
}
switch (ctl_command)

View File

@ -13,7 +13,7 @@
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/miscadmin.h,v 1.201 2008/02/20 22:46:24 tgl Exp $
* $PostgreSQL: pgsql/src/include/miscadmin.h,v 1.202 2008/04/23 13:44:59 mha Exp $
*
* NOTES
* some of the information in this file should be moved to other files.
@ -330,4 +330,8 @@ extern void ValidatePgVersion(const char *path);
extern void process_shared_preload_libraries(void);
extern void process_local_preload_libraries(void);
/* in access/transam/xlog.c */
extern bool BackupInProgress(void);
extern void CancelBackup(void);
#endif /* MISCADMIN_H */