*** 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 pg_ctl promote is run or a trigger file is found (trigger_file). Before failover, any WAL immediately available in the archive or in pg_xlog will be ! restored, but no attempt is made to connect to the master. --- 620,636 ---- when pg_ctl promote is run or a trigger file is found (trigger_file). Before failover, any WAL immediately available in the archive or in pg_xlog will be ! restored by default, but no attempt is made to connect to the master. ! If --immediate option is specified, 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, --immediate option can be used to ! ignore such problematic WAL data. *** a/doc/src/sgml/ref/pg_ctl-ref.sgml --- b/doc/src/sgml/ref/pg_ctl-ref.sgml *************** *** 93,98 **** PostgreSQL documentation --- 93,99 ---- datadir + *************** *** 404,409 **** PostgreSQL documentation --- 405,419 ---- + + + + Exit recovery immediately in promote mode. + + + + + *** 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();