diff options
author | Peter Eisentraut <peter@eisentraut.org> | 2021-01-18 08:49:10 +0100 |
---|---|---|
committer | Peter Eisentraut <peter@eisentraut.org> | 2021-01-18 09:04:04 +0100 |
commit | 15251c0a60be76eedee74ac0e94b433f9acca5af (patch) | |
tree | 4b77b0f77f165ea2d2091b84b5c2b8774bf60ea3 /src/backend/access/transam/xlog.c | |
parent | 708d165ddb92c54077a372acf6417e258dcb5fef (diff) | |
download | postgresql-15251c0a60be76eedee74ac0e94b433f9acca5af.tar.gz postgresql-15251c0a60be76eedee74ac0e94b433f9acca5af.zip |
Pause recovery for insufficient parameter settings
When certain parameters are changed on a physical replication primary,
this is communicated to standbys using the XLOG_PARAMETER_CHANGE WAL
record. The standby then checks whether its own settings are at least
as big as the ones on the primary. If not, the standby shuts down
with a fatal error.
This patch changes this behavior for hot standbys to pause recovery at
that point instead. That allows read traffic on the standby to
continue while database administrators figure out next steps. When
recovery is unpaused, the server shuts down (as before). The idea is
to fix the parameters while recovery is paused and then restart when
there is a maintenance window.
Reviewed-by: Sergei Kornilov <sk@zsrv.org>
Discussion: https://www.postgresql.org/message-id/flat/4ad69a4c-cc9b-0dfe-0352-8b1b0cd36c7b@2ndquadrant.com
Diffstat (limited to 'src/backend/access/transam/xlog.c')
-rw-r--r-- | src/backend/access/transam/xlog.c | 59 |
1 files changed, 54 insertions, 5 deletions
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index 199d911be76..470e113b331 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -6261,12 +6261,61 @@ static void RecoveryRequiresIntParameter(const char *param_name, int currValue, int minValue) { if (currValue < minValue) - ereport(ERROR, + { + if (LocalHotStandbyActive) + { + bool warned_for_promote = false; + + ereport(WARNING, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("hot standby is not possible because of insufficient parameter settings"), + errdetail("%s = %d is a lower setting than on the primary server, where its value was %d.", + param_name, + currValue, + minValue))); + + SetRecoveryPause(true); + + ereport(LOG, + (errmsg("recovery has paused"), + errdetail("If recovery is unpaused, the server will shut down."), + errhint("You can then restart the server after making the necessary configuration changes."))); + + while (RecoveryIsPaused()) + { + HandleStartupProcInterrupts(); + + if (CheckForStandbyTrigger()) + { + if (!warned_for_promote) + ereport(WARNING, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("promotion is not possible because of insufficient parameter settings"), + /* Repeat the detail from above so it's easy to find in the log. */ + errdetail("%s = %d is a lower setting than on the primary server, where its value was %d.", + param_name, + currValue, + minValue), + errhint("Restart the server after making the necessary configuration changes."))); + warned_for_promote = true; + } + + pgstat_report_wait_start(WAIT_EVENT_RECOVERY_PAUSE); + pg_usleep(1000000L); /* 1000 ms */ + pgstat_report_wait_end(); + } + } + + ereport(FATAL, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("hot standby is not possible because %s = %d is a lower setting than on the primary server (its value was %d)", - param_name, - currValue, - minValue))); + errmsg("recovery aborted because of insufficient parameter settings"), + /* Repeat the detail from above so it's easy to find in the log. */ + errdetail("%s = %d is a lower setting than on the primary server, where its value was %d.", + param_name, + currValue, + minValue), + errhint("You can restart the server after making the necessary configuration changes."))); + } } /* |