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:
parent
cf23b75b4d
commit
c979a1fefa
@ -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
|
PostgreSQL documentation
|
||||||
-->
|
-->
|
||||||
|
|
||||||
@ -133,9 +133,10 @@ PostgreSQL documentation
|
|||||||
In <option>stop</option> mode, the server that is running in
|
In <option>stop</option> mode, the server that is running in
|
||||||
the specified data directory is shut down. Three different
|
the specified data directory is shut down. Three different
|
||||||
shutdown methods can be selected with the <option>-m</option>
|
shutdown methods can be selected with the <option>-m</option>
|
||||||
option: <quote>Smart</quote> mode waits for all the clients to
|
option: <quote>Smart</quote> mode waits for online backup mode
|
||||||
disconnect. This is the default. <quote>Fast</quote> mode does
|
to finish and all the clients to disconnect. This is the default.
|
||||||
not wait for clients to disconnect. All active transactions are
|
<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
|
rolled back and clients are forcibly disconnected, then the
|
||||||
server is shut down. <quote>Immediate</quote> mode will abort
|
server is shut down. <quote>Immediate</quote> mode will abort
|
||||||
all server processes without a clean shutdown. This will lead to
|
all server processes without a clean shutdown. This will lead to
|
||||||
|
@ -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">
|
<chapter Id="runtime">
|
||||||
<title>Operating System Environment</title>
|
<title>Operating System Environment</title>
|
||||||
@ -1307,6 +1307,7 @@ sysctl -w vm.overcommit_memory=2
|
|||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
After receiving <systemitem>SIGTERM</systemitem>, the server
|
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
|
disallows new connections, but lets existing sessions end their
|
||||||
work normally. It shuts down only after all of the sessions
|
work normally. It shuts down only after all of the sessions
|
||||||
terminate normally. This is the <firstterm>Smart
|
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
|
The server disallows new connections and sends all existing
|
||||||
server processes <systemitem>SIGTERM</systemitem>, which will cause them
|
server processes <systemitem>SIGTERM</systemitem>, which will cause them
|
||||||
to abort their current transactions and exit promptly. It then
|
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>.
|
<firstterm>Fast Shutdown</firstterm>.
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2008, 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.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
|
* create a backup history file in pg_xlog (whence it will immediately be
|
||||||
* archived). The backup history file contains the same info found in
|
* archived). The backup history file contains the same info found in
|
||||||
* the label file, plus the backup-end time and WAL location.
|
* the label file, plus the backup-end time and WAL location.
|
||||||
|
* Note: different from CancelBackup which just cancels online backup mode.
|
||||||
*/
|
*/
|
||||||
Datum
|
Datum
|
||||||
pg_stop_backup(PG_FUNCTION_ARGS)
|
pg_stop_backup(PG_FUNCTION_ARGS)
|
||||||
@ -7063,3 +7064,52 @@ rm_redo_error_callback(void *arg)
|
|||||||
|
|
||||||
pfree(buf.data);
|
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)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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
|
* NOTES
|
||||||
*
|
*
|
||||||
@ -253,6 +253,7 @@ typedef enum
|
|||||||
PM_INIT, /* postmaster starting */
|
PM_INIT, /* postmaster starting */
|
||||||
PM_STARTUP, /* waiting for startup subprocess */
|
PM_STARTUP, /* waiting for startup subprocess */
|
||||||
PM_RUN, /* normal "database is alive" state */
|
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_WAIT_BACKENDS, /* waiting for live backends to exit */
|
||||||
PM_SHUTDOWN, /* waiting for bgwriter to do shutdown ckpt */
|
PM_SHUTDOWN, /* waiting for bgwriter to do shutdown ckpt */
|
||||||
PM_SHUTDOWN_2, /* waiting for archiver to finish */
|
PM_SHUTDOWN_2, /* waiting for archiver to finish */
|
||||||
@ -1724,8 +1725,12 @@ processCancelRequest(Port *port, void *pkt)
|
|||||||
static enum CAC_state
|
static enum CAC_state
|
||||||
canAcceptConnections(void)
|
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)
|
if (Shutdown > NoShutdown)
|
||||||
return CAC_SHUTDOWN; /* shutdown is pending */
|
return CAC_SHUTDOWN; /* shutdown is pending */
|
||||||
@ -1965,11 +1970,12 @@ pmdie(SIGNAL_ARGS)
|
|||||||
/* and the walwriter too */
|
/* and the walwriter too */
|
||||||
if (WalWriterPID != 0)
|
if (WalWriterPID != 0)
|
||||||
signal_child(WalWriterPID, SIGTERM);
|
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 will take the next step.
|
||||||
*/
|
*/
|
||||||
PostmasterStateMachine();
|
PostmasterStateMachine();
|
||||||
@ -2011,6 +2017,13 @@ pmdie(SIGNAL_ARGS)
|
|||||||
* PostmasterStateMachine will take the next step.
|
* PostmasterStateMachine will take the next step.
|
||||||
*/
|
*/
|
||||||
PostmasterStateMachine();
|
PostmasterStateMachine();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Terminate backup mode to avoid recovery after a
|
||||||
|
* clean fast shutdown.
|
||||||
|
*/
|
||||||
|
CancelBackup();
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SIGQUIT:
|
case SIGQUIT:
|
||||||
@ -2552,6 +2565,20 @@ LogChildExit(int lev, const char *procname, int pid, int exitstatus)
|
|||||||
static void
|
static void
|
||||||
PostmasterStateMachine(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
|
* 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.
|
* exit, see if they're all gone, and change state if so.
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
*
|
*
|
||||||
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
|
* 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 postopts_file[MAXPGPATH];
|
||||||
static char pid_file[MAXPGPATH];
|
static char pid_file[MAXPGPATH];
|
||||||
static char conf_file[MAXPGPATH];
|
static char conf_file[MAXPGPATH];
|
||||||
|
static char backup_file[MAXPGPATH];
|
||||||
|
|
||||||
#if defined(HAVE_GETRLIMIT) && defined(RLIMIT_CORE)
|
#if defined(HAVE_GETRLIMIT) && defined(RLIMIT_CORE)
|
||||||
static void unlimit_core_size(void);
|
static void unlimit_core_size(void);
|
||||||
@ -731,6 +732,7 @@ do_stop(void)
|
|||||||
{
|
{
|
||||||
int cnt;
|
int cnt;
|
||||||
pgpid_t pid;
|
pgpid_t pid;
|
||||||
|
struct stat statbuf;
|
||||||
|
|
||||||
pid = get_pgpid();
|
pid = get_pgpid();
|
||||||
|
|
||||||
@ -763,6 +765,12 @@ do_stop(void)
|
|||||||
}
|
}
|
||||||
else
|
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..."));
|
print_msg(_("waiting for server to shut down..."));
|
||||||
|
|
||||||
for (cnt = 0; cnt < wait_seconds; cnt++)
|
for (cnt = 0; cnt < wait_seconds; cnt++)
|
||||||
@ -799,6 +807,7 @@ do_restart(void)
|
|||||||
{
|
{
|
||||||
int cnt;
|
int cnt;
|
||||||
pgpid_t pid;
|
pgpid_t pid;
|
||||||
|
struct stat statbuf;
|
||||||
|
|
||||||
pid = get_pgpid();
|
pid = get_pgpid();
|
||||||
|
|
||||||
@ -833,6 +842,12 @@ do_restart(void)
|
|||||||
exit(1);
|
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..."));
|
print_msg(_("waiting for server to shut down..."));
|
||||||
|
|
||||||
/* always wait for restart */
|
/* always wait for restart */
|
||||||
@ -1883,6 +1898,7 @@ main(int argc, char **argv)
|
|||||||
snprintf(postopts_file, MAXPGPATH, "%s/postmaster.opts", pg_data);
|
snprintf(postopts_file, MAXPGPATH, "%s/postmaster.opts", pg_data);
|
||||||
snprintf(pid_file, MAXPGPATH, "%s/postmaster.pid", pg_data);
|
snprintf(pid_file, MAXPGPATH, "%s/postmaster.pid", pg_data);
|
||||||
snprintf(conf_file, MAXPGPATH, "%s/postgresql.conf", pg_data);
|
snprintf(conf_file, MAXPGPATH, "%s/postgresql.conf", pg_data);
|
||||||
|
snprintf(backup_file, MAXPGPATH, "%s/backup_label", pg_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (ctl_command)
|
switch (ctl_command)
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2008, 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/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
|
* NOTES
|
||||||
* some of the information in this file should be moved to other files.
|
* 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_shared_preload_libraries(void);
|
||||||
extern void process_local_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 */
|
#endif /* MISCADMIN_H */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user