Hi, I'd like to propose to add new option "--immediate" to pg_ctl promote. When this option is set, recovery ignores any WAL data which have not been replayed yet and exits immediately. Patch attached.
This promotion is faster than normal one but can cause data loss. So it's useful if we want to switch the server to normal operation as soon as possible at the expense of durability. Also imagine the case where, while recovery is being delayed (by a time-delayed standby which was introduced in 9.4) or paused (by pg_xlog_replay_pause), you find that subsequent WAL data can cause a disaster to happen (for example, WAL data indicating an unexpected deletion of important database). In this case, this immediate promotion can be used to ignore such problematic WAL data. With the patch, "--immediate" option controls whether immediate promotion is performed or not. OTOH, we can extend "-m" option that pg_ctl stop has already used so that it controls also the mode of promotion. But when we discussed this feature before, someone disagreed to do that because shutdown mode and promotion mode are different concepts. For example, if "smart" is specified as mode, how should the promotion work? I agree with him, and just added new separate option. Thought? Regards, -- Fujii Masao
*** a/doc/src/sgml/high-availability.sgml --- b/doc/src/sgml/high-availability.sgml *************** *** 620,626 **** protocol to make nodes agree on a serializable transactional order. when <command>pg_ctl promote</> is run or a trigger file is found (<varname>trigger_file</>). Before failover, any WAL immediately available in the archive or in <filename>pg_xlog</> will be ! restored, but no attempt is made to connect to the master. </para> </sect2> --- 620,636 ---- when <command>pg_ctl promote</> is run or a trigger file is found (<varname>trigger_file</>). Before failover, any WAL immediately available in the archive or in <filename>pg_xlog</> will be ! restored by default, but no attempt is made to connect to the master. ! If <literal>--immediate</> option is specified, <command>pg_ctl promote</> ! makes recovery ignore any WAL that have not been replayed yet ! and exit immediately. This promotion is faster but can cause data loss. ! So it's useful if you want to switch the server to normal operation ! as soon as possible at the expense of durability. ! While recovery is being delayed (by a time-delayed standby) or paused, ! you may find that subsequent WAL data can cause a disaster to happen ! (for example, WAL data indicating an unexpected deletion of important ! database). In this case, <literal>--immediate</> option can be used to ! ignore such problematic WAL data. </para> </sect2> *** a/doc/src/sgml/ref/pg_ctl-ref.sgml --- b/doc/src/sgml/ref/pg_ctl-ref.sgml *************** *** 93,98 **** PostgreSQL documentation --- 93,99 ---- <arg choice="plain"><option>promote</option></arg> <arg choice="opt"><option>-s</option></arg> <arg choice="opt"><option>-D</option> <replaceable>datadir</replaceable></arg> + <arg choice="opt"><option>--immediate</option></arg> </cmdsynopsis> <cmdsynopsis> *************** *** 404,409 **** PostgreSQL documentation --- 405,419 ---- </varlistentry> <varlistentry> + <term><option>--immediate</option></term> + <listitem> + <para> + Exit recovery immediately in promote mode. + </para> + </listitem> + </varlistentry> + + <varlistentry> <term><option>-?</></term> <term><option>--help</></term> <listitem> *** a/src/backend/access/transam/xlog.c --- b/src/backend/access/transam/xlog.c *************** *** 74,79 **** extern uint32 bootstrap_data_checksum_version; --- 74,80 ---- #define RECOVERY_COMMAND_DONE "recovery.done" #define PROMOTE_SIGNAL_FILE "promote" #define FALLBACK_PROMOTE_SIGNAL_FILE "fallback_promote" + #define IMMEDIATE_PROMOTE_SIGNAL_FILE "immediate_promote" /* User-settable parameters */ *************** *** 240,245 **** bool StandbyMode = false; --- 241,249 ---- /* whether request for fast promotion has been made yet */ static bool fast_promote = false; + /* whether request for immediate promotion has been made yet */ + static bool immediate_promote = false; + /* * if recoveryStopsBefore/After returns true, it saves information of the stop * point here *************** *** 6761,6766 **** StartupXLOG(void) --- 6765,6777 ---- recoveryPausesHere(); } + /* + * In immediate promotion, we ignore WAL data that have not + * been replayed yet and exit recovery immediately. + */ + if (immediate_promote) + break; + /* Setup error traceback support for ereport() */ errcallback.callback = rm_redo_error_callback; errcallback.arg = (void *) record; *************** *** 11299,11315 **** CheckForStandbyTrigger(void) --- 11310,11341 ---- * Startup process do the unlink. This allows Startup to know whether * it should create a full checkpoint before starting up (fallback * mode). Fast promotion takes precedence. + * + * Also the promote file allows Startup to know whether it should + * exit recovery immediately without replaying the remaining WAL + * data. Since immediate promotion has a risk of data loss, it's + * treated as lowest-priority mode. */ if (stat(PROMOTE_SIGNAL_FILE, &stat_buf) == 0) { unlink(PROMOTE_SIGNAL_FILE); unlink(FALLBACK_PROMOTE_SIGNAL_FILE); + unlink(IMMEDIATE_PROMOTE_SIGNAL_FILE); fast_promote = true; + immediate_promote = false; } else if (stat(FALLBACK_PROMOTE_SIGNAL_FILE, &stat_buf) == 0) { unlink(FALLBACK_PROMOTE_SIGNAL_FILE); + unlink(IMMEDIATE_PROMOTE_SIGNAL_FILE); fast_promote = false; + immediate_promote = false; + } + else if(stat(IMMEDIATE_PROMOTE_SIGNAL_FILE, &stat_buf) == 0) + { + unlink(IMMEDIATE_PROMOTE_SIGNAL_FILE); + fast_promote = true; + immediate_promote = true; } ereport(LOG, (errmsg("received promote request"))); *************** *** 11350,11356 **** CheckPromoteSignal(void) struct stat stat_buf; if (stat(PROMOTE_SIGNAL_FILE, &stat_buf) == 0 || ! stat(FALLBACK_PROMOTE_SIGNAL_FILE, &stat_buf) == 0) return true; return false; --- 11376,11383 ---- struct stat stat_buf; if (stat(PROMOTE_SIGNAL_FILE, &stat_buf) == 0 || ! stat(FALLBACK_PROMOTE_SIGNAL_FILE, &stat_buf) == 0 || ! stat(IMMEDIATE_PROMOTE_SIGNAL_FILE, &stat_buf) == 0) return true; return false; *** a/src/bin/pg_ctl/pg_ctl.c --- b/src/bin/pg_ctl/pg_ctl.c *************** *** 80,85 **** static bool wait_set = false; --- 80,86 ---- static int wait_seconds = DEFAULT_WAIT; static bool silent_mode = false; static ShutdownMode shutdown_mode = SMART_MODE; + static int immediate_promote = 0; static int sig = SIGTERM; /* default */ static CtlCommand ctl_command = NO_COMMAND; static char *pg_data = NULL; *************** *** 1165,1175 **** do_promote(void) } /* ! * For 9.3 onwards, "fast" promotion is performed. Promotion with a full ! * checkpoint is still possible by writing a file called ! * "fallback_promote" instead of "promote" */ ! snprintf(promote_file, MAXPGPATH, "%s/promote", pg_data); if ((prmfile = fopen(promote_file, "w")) == NULL) { --- 1166,1182 ---- } /* ! * Create a promote file according to the specified mode. ! * ! * For 9.3 onwards, "fast" promotion is performed (i.e., end-of-recovery ! * checkpoint is skipped) by default. Promotion with a full checkpoint ! * is still possible by writing a file called "fallback_promote" instead ! * of "promote" and "immediate_promote" */ ! if (immediate_promote) ! snprintf(promote_file, MAXPGPATH, "%s/immediate_promote", pg_data); ! else ! snprintf(promote_file, MAXPGPATH, "%s/promote", pg_data); if ((prmfile = fopen(promote_file, "w")) == NULL) { *************** *** 1872,1878 **** do_help(void) " [-o \"OPTIONS\"]\n"), progname); printf(_(" %s reload [-D DATADIR] [-s]\n"), progname); printf(_(" %s status [-D DATADIR]\n"), progname); ! printf(_(" %s promote [-D DATADIR] [-s]\n"), progname); printf(_(" %s kill SIGNALNAME PID\n"), progname); #if defined(WIN32) || defined(__CYGWIN__) printf(_(" %s register [-N SERVICENAME] [-U USERNAME] [-P PASSWORD] [-D DATADIR]\n" --- 1879,1885 ---- " [-o \"OPTIONS\"]\n"), progname); printf(_(" %s reload [-D DATADIR] [-s]\n"), progname); printf(_(" %s status [-D DATADIR]\n"), progname); ! printf(_(" %s promote [-D DATADIR] [-s] [--immediate]\n"), progname); printf(_(" %s kill SIGNALNAME PID\n"), progname); #if defined(WIN32) || defined(__CYGWIN__) printf(_(" %s register [-N SERVICENAME] [-U USERNAME] [-P PASSWORD] [-D DATADIR]\n" *************** *** 1913,1918 **** do_help(void) --- 1920,1928 ---- printf(_(" fast quit directly, with proper shutdown\n")); printf(_(" immediate quit without complete shutdown; will lead to recovery on restart\n")); + printf(_("\nOptions for promote:\n")); + printf(_(" --immediate exit recovery immediately; unreplayed logs are ignored\n")); + printf(_("\nAllowed signal names for kill:\n")); printf(" ABRT HUP INT QUIT TERM USR1 USR2\n"); *************** *** 2085,2090 **** main(int argc, char **argv) --- 2095,2101 ---- {"silent", no_argument, NULL, 's'}, {"timeout", required_argument, NULL, 't'}, {"core-files", no_argument, NULL, 'c'}, + {"immediate", no_argument, &immediate_promote, 1}, {NULL, 0, NULL, 0} }; *************** *** 2225,2230 **** main(int argc, char **argv) --- 2236,2243 ---- case 'c': allow_core_files = true; break; + case 0: + break; default: /* getopt_long already issued a suitable error message */ do_advice();
-- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers