From: Alvaro Herrera <alvherre@2ndquadrant.com>
To: Sergei Kornilov <sk@zsrv.org>
Cc: Michael Paquier <michael@paquier.xyz>
Cc: Tomas Vondra <tomas.vondra@2ndquadrant.com>
Cc: Kyotaro Horiguchi <horikyota.ntt@gmail.com>
Cc: andres@anarazel.de <andres@anarazel.de>
Cc: david@pgmasters.net <david@pgmasters.net>
Cc: pgsql-hackers@postgresql.org <pgsql-hackers@postgresql.org>
Cc: Peter Eisentraut <peter.eisentraut@2ndquadrant.com>
Subject: Re: allow online change primary_conninfo
Date: Wed, 25 Mar 2020 21:08:12 -0300
Message-ID: <20200326000812.GA18798@alvherre.pgsql> (raw)
In-Reply-To: <20200324214922.GA27503@alvherre.pgsql>
On 2020-Mar-24, Alvaro Herrera wrote:
> I think the startup sighup handler should be in startup.c, not xlog.c,
> which has enough random code already. We can add an accessor in xlog.c
> to let changing the walrcv status flag, to be called from the signal
> handler.
... as in the attached version.
Sergei included LOG messages to indicate which setting has been changed.
I put these in "#if 0" for now, but I'm thinking to remove these
altogether; we already have LOG messages when a setting changes value,
per ProcessConfigFileInternal(); the log sequence looks like this, taken
from tmp_check/log/001_stream_rep_standby_2.log after running the tests:
2020-03-25 20:54:19.413 -03 [17493] LOG: received SIGHUP, reloading configuration files
2020-03-25 20:54:19.415 -03 [17493] LOG: parameter "primary_slot_name" changed to "standby_2"
2020-03-25 20:54:19.415 -03 [17493] LOG: parameter "wal_receiver_status_interval" changed to "1"
2020-03-25 20:54:19.422 -03 [17569] LOG: started streaming WAL from primary at 0/3000000 on timeline 1
2020-03-25 20:54:19.426 -03 [17494] LOG: wal receiver process shutdown requested
2020-03-25 20:54:19.426 -03 [17569] FATAL: terminating walreceiver process due to administrator command
2020-03-25 20:54:19.433 -03 [17572] LOG: started streaming WAL from primary at 0/3000000 on timeline 1
which looks sufficient. Maybe we can reword that new message, say "wal
receiver process shutdown forced by parameter change". Not sure if we
can or should adjust the FATAL line; probably not worth the trouble.
Thoughts welcome. I'm thinking on getting this applied shortly.
--
Álvaro Herrera https://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services
Attachments:download all (3 files, .tar.gz)v10-0001-Set-wal_receiver_create_temp_slot-PGC_POSTMASTER.patch (text/x-diff, 10.2K) download
From 0bd43454e2981d9551b12424902d537674d48e31 Mon Sep 17 00:00:00 2001
From: Alvaro Herrera <alvherre@alvh.no-ip.org>
Date: Wed, 25 Mar 2020 20:48:44 -0300
Subject: [PATCH v10 1/3] Set wal_receiver_create_temp_slot PGC_POSTMASTER
and off by default
---
doc/src/sgml/config.sgml | 6 +--
src/backend/access/transam/xlog.c | 3 +-
src/backend/replication/walreceiver.c | 46 +++++++------------
src/backend/replication/walreceiverfuncs.c | 28 +++++++++--
src/backend/utils/misc/guc.c | 4 +-
src/backend/utils/misc/postgresql.conf.sample | 4 +-
src/include/access/xlog.h | 1 +
src/include/replication/walreceiver.h | 4 +-
8 files changed, 50 insertions(+), 46 deletions(-)
diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgmlindex 355b408b0a..b5de6c3237 100644--- a/doc/src/sgml/config.sgml+++ b/doc/src/sgml/config.sgml@@ -4163,11 +4163,7 @@ ANY <replaceable class="parameter">num_sync</replaceable> ( <replaceable class="
Specifies whether a WAL receiver should create a temporary replication
slot on the remote instance when no permanent replication slot to use
has been configured (using <xref linkend="guc-primary-slot-name"/>).
- The default is on. The only reason to turn this off would be if the- remote instance is currently out of available replication slots. This- parameter can only be set in the <filename>postgresql.conf</filename>- file or on the server command line. Changes only take effect when the- WAL receiver process starts a new connection.+ The default is off. This parameter can only be set at server start.
</para>
</listitem>
</varlistentry>
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.cindex 7621fc05e2..19df1d5a80 100644--- a/src/backend/access/transam/xlog.c+++ b/src/backend/access/transam/xlog.c@@ -290,6 +290,7 @@ bool StandbyModeRequested = false;
char *PrimaryConnInfo = NULL;
char *PrimarySlotName = NULL;
char *PromoteTriggerFile = NULL;
+bool wal_receiver_create_temp_slot = false;
/* are we currently in standby mode? */
bool StandbyMode = false;
@@ -11975,7 +11976,7 @@ WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool randAccess,
}
curFileTLI = tli;
RequestXLogStreaming(tli, ptr, PrimaryConnInfo,
- PrimarySlotName);+ PrimarySlotName, wal_receiver_create_temp_slot);
receivedUpto = 0;
}
diff --git a/src/backend/replication/walreceiver.c b/src/backend/replication/walreceiver.cindex 25e0333c9e..779d19f1c1 100644--- a/src/backend/replication/walreceiver.c+++ b/src/backend/replication/walreceiver.c@@ -15,6 +15,12 @@
* WalRcv->receivedUpto variable in shared memory, to inform the startup
* process of how far it can proceed with XLOG replay.
*
+ * WAL receivers cannot load directly GUC parameters used when establishing+ * their connection to the primary, and rely on parameter values passed down+ * by the startup process when WAL streaming is requested. This applies+ * to for example the replication slot creation and the connection string to+ * use for the connection with the primary.+ *
* If the primary server ends streaming, but doesn't disconnect, walreceiver
* goes into "waiting" mode, and waits for the startup process to give new
* instructions. The startup process will treat that the same as
@@ -74,7 +80,6 @@
/* GUC variables */
-bool wal_receiver_create_temp_slot;
int wal_receiver_status_interval;
int wal_receiver_timeout;
bool hot_standby_feedback;
@@ -349,42 +354,23 @@ WalReceiverMain(void)
WalRcvFetchTimeLineHistoryFiles(startpointTLI, primaryTLI);
/*
- * Create temporary replication slot if no slot name is configured or- * the slot from the previous run was temporary, unless- * wal_receiver_create_temp_slot is disabled. We also need to handle- * the case where the previous run used a temporary slot but- * wal_receiver_create_temp_slot was changed in the meantime. In that- * case, we delete the old slot name in shared memory. (This would+ * Create temporary replication slot if requested. In that+ * case, we update slot name in shared memory. (This would
* all be a bit easier if we just didn't copy the slot name into
* shared memory, since we won't need it again later, but then we
* can't see the slot name in the stats views.)
*/
- if (slotname[0] == '\0' || is_temp_slot)+ if (is_temp_slot)
{
- bool changed = false;+ snprintf(slotname, sizeof(slotname),+ "pg_walreceiver_%lld",+ (long long int) walrcv_get_backend_pid(wrconn));- if (wal_receiver_create_temp_slot)- {- snprintf(slotname, sizeof(slotname),- "pg_walreceiver_%lld",- (long long int) walrcv_get_backend_pid(wrconn));+ walrcv_create_slot(wrconn, slotname, true, 0, NULL);- walrcv_create_slot(wrconn, slotname, true, 0, NULL);- changed = true;- }- else if (slotname[0] != '\0')- {- slotname[0] = '\0';- changed = true;- }-- if (changed)- {- SpinLockAcquire(&walrcv->mutex);- strlcpy(walrcv->slotname, slotname, NAMEDATALEN);- walrcv->is_temp_slot = wal_receiver_create_temp_slot;- SpinLockRelease(&walrcv->mutex);- }+ SpinLockAcquire(&walrcv->mutex);+ strlcpy(walrcv->slotname, slotname, NAMEDATALEN);+ SpinLockRelease(&walrcv->mutex);
}
/*
diff --git a/src/backend/replication/walreceiverfuncs.c b/src/backend/replication/walreceiverfuncs.cindex 89c903e45a..21d1823607 100644--- a/src/backend/replication/walreceiverfuncs.c+++ b/src/backend/replication/walreceiverfuncs.c@@ -215,13 +215,19 @@ ShutdownWalRcv(void)
/*
* Request postmaster to start walreceiver.
*
- * recptr indicates the position where streaming should begin, conninfo- * is a libpq connection string to use, and slotname is, optionally, the name- * of a replication slot to acquire.+ * "recptr" indicates the position where streaming should begin. "conninfo"+ * is a libpq connection string to use. "slotname" is, optionally, the name+ * of a replication slot to acquire. "create_temp_slot" indicates to create+ * a temporary slot when no "slotname" is given.+ *+ * WAL receivers do not directly load GUC parameters used for the connection+ * to the primary, and rely on the values passed down by the caller of this+ * routine instead. Hence, the addition of any new parameters should happen+ * through this code path.
*/
void
RequestXLogStreaming(TimeLineID tli, XLogRecPtr recptr, const char *conninfo,
- const char *slotname)+ const char *slotname, bool create_temp_slot)
{
WalRcvData *walrcv = WalRcv;
bool launch = false;
@@ -248,10 +254,22 @@ RequestXLogStreaming(TimeLineID tli, XLogRecPtr recptr, const char *conninfo,
else
walrcv->conninfo[0] = '\0';
- if (slotname != NULL)+ /*+ * Use configured replication slot if present, and ignore the value+ * of create_temp_slot as the slot name should be persistent. Otherwise,+ * use create_temp_slot to determine whether this WAL receiver should+ * create a temporary slot by itself and use it, or not.+ */+ if (slotname != NULL && slotname[0] != '\0')+ {
strlcpy((char *) walrcv->slotname, slotname, NAMEDATALEN);
+ walrcv->is_temp_slot = false;+ }
else
+ {
walrcv->slotname[0] = '\0';
+ walrcv->is_temp_slot = create_temp_slot;+ }
if (walrcv->walRcvState == WALRCV_STOPPED)
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.cindex af876d1f01..2c3cbbaa68 100644--- a/src/backend/utils/misc/guc.c+++ b/src/backend/utils/misc/guc.c@@ -2050,11 +2050,11 @@ static struct config_bool ConfigureNamesBool[] =
},
{
- {"wal_receiver_create_temp_slot", PGC_SIGHUP, REPLICATION_STANDBY,+ {"wal_receiver_create_temp_slot", PGC_POSTMASTER, REPLICATION_STANDBY,
gettext_noop("Sets whether a WAL receiver should create a temporary replication slot if no permanent slot is configured."),
},
&wal_receiver_create_temp_slot,
- true,+ false,
NULL, NULL, NULL
},
diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sampleindex aa44f0c9bf..f2e55d1bd3 100644--- a/src/backend/utils/misc/postgresql.conf.sample+++ b/src/backend/utils/misc/postgresql.conf.sample@@ -321,7 +321,9 @@
#max_standby_streaming_delay = 30s # max delay before canceling queries
# when reading streaming WAL;
# -1 allows indefinite delay
-#wal_receiver_create_temp_slot = on # create temp slot if primary_slot_name not set+#wal_receiver_create_temp_slot = off # Create temp slot if primary_slot_name+ # is not set.+ # (change requires restart)
#wal_receiver_status_interval = 10s # send replies at least this often
# 0 disables
#hot_standby_feedback = off # send info from standby to prevent
diff --git a/src/include/access/xlog.h b/src/include/access/xlog.hindex 331497bcfb..a4485efc00 100644--- a/src/include/access/xlog.h+++ b/src/include/access/xlog.h@@ -129,6 +129,7 @@ extern int recoveryTargetAction;
extern int recovery_min_apply_delay;
extern char *PrimaryConnInfo;
extern char *PrimarySlotName;
+extern bool wal_receiver_create_temp_slot;
/* indirectly set via GUC system */
extern TransactionId recoveryTargetXid;
diff --git a/src/include/replication/walreceiver.h b/src/include/replication/walreceiver.hindex e08afc6548..cf3e43128c 100644--- a/src/include/replication/walreceiver.h+++ b/src/include/replication/walreceiver.h@@ -23,7 +23,6 @@
#include "utils/tuplestore.h"
/* user-settable parameters */
-extern bool wal_receiver_create_temp_slot;
extern int wal_receiver_status_interval;
extern int wal_receiver_timeout;
extern bool hot_standby_feedback;
@@ -321,7 +320,8 @@ extern void ShutdownWalRcv(void);
extern bool WalRcvStreaming(void);
extern bool WalRcvRunning(void);
extern void RequestXLogStreaming(TimeLineID tli, XLogRecPtr recptr,
- const char *conninfo, const char *slotname);+ const char *conninfo, const char *slotname,+ bool create_temp_slot);
extern XLogRecPtr GetWalRcvWriteRecPtr(XLogRecPtr *latestChunkStart, TimeLineID *receiveTLI);
extern int GetReplicationApplyDelay(void);
extern int GetReplicationTransferLatency(void);
--
2.20.1
v10-0002-Allow-changing-primary_conninfo-and-primary_slot.patch (text/x-diff, 15.6K) download
From 2aedb8e73c1b22c49763d09559f5489bbd2e07b7 Mon Sep 17 00:00:00 2001
From: Alvaro Herrera <alvherre@alvh.no-ip.org>
Date: Wed, 25 Mar 2020 20:48:56 -0300
Subject: [PATCH v10 2/3] Allow changing primary_conninfo and primary_slot_name
in SIGHUP
---
doc/src/sgml/config.sgml | 16 +-
src/backend/access/transam/xlog.c | 144 ++++++++++++------
src/backend/access/transam/xlogreader.c | 6 +-
src/backend/postmaster/startup.c | 30 +++-
src/backend/replication/walreceiver.c | 6 +-
src/backend/utils/misc/guc.c | 4 +-
src/backend/utils/misc/postgresql.conf.sample | 2 -
src/include/access/xlog.h | 2 +
src/test/recovery/t/001_stream_rep.pl | 24 ++-
9 files changed, 173 insertions(+), 61 deletions(-)
diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgmlindex b5de6c3237..4d17dafa7e 100644--- a/doc/src/sgml/config.sgml+++ b/doc/src/sgml/config.sgml@@ -4028,9 +4028,15 @@ ANY <replaceable class="parameter">num_sync</replaceable> ( <replaceable class="
<varname>primary_conninfo</varname> string.
</para>
<para>
- This parameter can only be set at server start.+ This parameter can only be set in the <filename>postgresql.conf</filename>+ file or on the server command line.
This setting has no effect if the server is not in standby mode.
</para>
+ <para>+ If <varname>primary_conninfo</varname> is changed while WAL receiver is running,+ the WAL receiver shuts down and then restarts with new setting,+ except when primary_conninfo is an empty string.+ </para>
</listitem>
</varlistentry>
<varlistentry id="guc-primary-slot-name" xreflabel="primary_slot_name">
@@ -4045,9 +4051,13 @@ ANY <replaceable class="parameter">num_sync</replaceable> ( <replaceable class="
connecting to the sending server via streaming replication to control
resource removal on the upstream node
(see <xref linkend="streaming-replication-slots"/>).
- This parameter can only be set at server start.+ This parameter can only be set in the <filename>postgresql.conf</filename>+ file or on the server command line.
This setting has no effect if <varname>primary_conninfo</varname> is not
- set.+ set or the server is not in standby mode.+ </para>+ <para>+ The WAL receiver is restarted after an update of <varname>primary_slot_name</varname>.
</para>
</listitem>
</varlistentry>
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.cindex 19df1d5a80..fab6187120 100644--- a/src/backend/access/transam/xlog.c+++ b/src/backend/access/transam/xlog.c@@ -816,9 +816,13 @@ static XLogSource readSource = XLOG_FROM_ANY;
* currently have a WAL file open. If lastSourceFailed is set, our last
* attempt to read from currentSource failed, and we should try another source
* next.
+ *+ * pendingWalRcvRestart is set when a config change occurs that requires a+ * walreceiver restart. This is only valid in XLOG_FROM_STREAM state.
*/
static XLogSource currentSource = XLOG_FROM_ANY;
static bool lastSourceFailed = false;
+static bool pendingWalRcvRestart = false;
typedef struct XLogPageReadPrivate
{
@@ -11905,6 +11909,7 @@ WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool randAccess,
for (;;)
{
XLogSource oldSource = currentSource;
+ bool startWalReceiver = false;
/*
* First check if we failed to read from the current source, and
@@ -11939,53 +11944,11 @@ WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool randAccess,
return false;
/*
- * If primary_conninfo is set, launch walreceiver to try- * to stream the missing WAL.- *- * If fetching_ckpt is true, RecPtr points to the initial- * checkpoint location. In that case, we use RedoStartLSN- * as the streaming start position instead of RecPtr, so- * that when we later jump backwards to start redo at- * RedoStartLSN, we will have the logs streamed already.- */- if (PrimaryConnInfo && strcmp(PrimaryConnInfo, "") != 0)- {- XLogRecPtr ptr;- TimeLineID tli;-- if (fetching_ckpt)- {- ptr = RedoStartLSN;- tli = ControlFile->checkPointCopy.ThisTimeLineID;- }- else- {- ptr = RecPtr;-- /*- * Use the record begin position to determine the- * TLI, rather than the position we're reading.- */- tli = tliOfPointInHistory(tliRecPtr, expectedTLEs);-- if (curFileTLI > 0 && tli < curFileTLI)- elog(ERROR, "according to history file, WAL location %X/%X belongs to timeline %u, but previous recovered WAL file came from timeline %u",- (uint32) (tliRecPtr >> 32),- (uint32) tliRecPtr,- tli, curFileTLI);- }- curFileTLI = tli;- RequestXLogStreaming(tli, ptr, PrimaryConnInfo,- PrimarySlotName, wal_receiver_create_temp_slot);- receivedUpto = 0;- }-- /*- * Move to XLOG_FROM_STREAM state in either case. We'll- * get immediate failure if we didn't launch walreceiver,- * and move on to the next state.+ * Move to XLOG_FROM_STREAM state, and set to start a+ * walreceiver if necessary.
*/
currentSource = XLOG_FROM_STREAM;
+ startWalReceiver = true;
break;
case XLOG_FROM_STREAM:
@@ -12137,7 +12100,70 @@ WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool randAccess,
Assert(StandbyMode);
/*
- * Check if WAL receiver is still active.+ * First, shutdown walreceiver if its restart has been+ * requested -- but no point if we're already slated for+ * starting it.+ */+ if (pendingWalRcvRestart && !startWalReceiver)+ {+ ShutdownWalRcv();++ /*+ * Re-scan for possible new timelines if we were+ * requested to recover to the latest timeline.+ */+ if (recoveryTargetTimeLineGoal ==+ RECOVERY_TARGET_TIMELINE_LATEST)+ rescanLatestTimeLine();++ startWalReceiver = true;+ }+ pendingWalRcvRestart = false;++ /*+ * Launch walreceiver if needed.+ *+ * If fetching_ckpt is true, RecPtr points to the initial+ * checkpoint location. In that case, we use RedoStartLSN+ * as the streaming start position instead of RecPtr, so+ * that when we later jump backwards to start redo at+ * RedoStartLSN, we will have the logs streamed already.+ */+ if (startWalReceiver &&+ PrimaryConnInfo && strcmp(PrimaryConnInfo, "") != 0)+ {+ XLogRecPtr ptr;+ TimeLineID tli;++ if (fetching_ckpt)+ {+ ptr = RedoStartLSN;+ tli = ControlFile->checkPointCopy.ThisTimeLineID;+ }+ else+ {+ ptr = RecPtr;++ /*+ * Use the record begin position to determine the+ * TLI, rather than the position we're reading.+ */+ tli = tliOfPointInHistory(tliRecPtr, expectedTLEs);++ if (curFileTLI > 0 && tli < curFileTLI)+ elog(ERROR, "according to history file, WAL location %X/%X belongs to timeline %u, but previous recovered WAL file came from timeline %u",+ (uint32) (tliRecPtr >> 32),+ (uint32) tliRecPtr,+ tli, curFileTLI);+ }+ curFileTLI = tli;+ RequestXLogStreaming(tli, ptr, PrimaryConnInfo,+ PrimarySlotName, wal_receiver_create_temp_slot);+ receivedUpto = 0;+ }++ /*+ * Check if WAL receiver is active or wait to start up.
*/
if (!WalRcvStreaming())
{
@@ -12265,6 +12291,32 @@ WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool randAccess,
return false; /* not reached */
}
+void+StartupRequestWalReceiverRestart(void)+{+ if (currentSource == XLOG_FROM_STREAM && WalRcvRunning())+ {+ ereport(LOG,+ (errmsg("wal receiver process shutdown requested")));+#if 0+ if (conninfoChanged && strcmp(PrimaryConnInfo, "") == 0)+ ereport(LOG,+ (errmsg("shutting down walreceiver")+ "primary_conninfo")));+ else if (conninfoChanged && slotnameChanged)+ ereport(LOG,+ (errmsg("The WAL receiver is going to be restarted due to change of %s and %s",+ "primary_conninfo", "primary_slot_name")));+ else+ ereport(LOG,+ (errmsg("The WAL receiver is going to be restarted due to change of %s",+ conninfoChanged ? "primary_conninfo" : "primary_slot_name")));+#endif++ pendingWalRcvRestart = true;+ }+}+
/*
* Determine what log level should be used to report a corrupt WAL record
* in the current WAL page, previously read by XLogPageRead().
diff --git a/src/backend/access/transam/xlogreader.c b/src/backend/access/transam/xlogreader.cindex 32f02256ed..f3fea5132f 100644--- a/src/backend/access/transam/xlogreader.c+++ b/src/backend/access/transam/xlogreader.c@@ -585,9 +585,9 @@ ReadPageInternal(XLogReaderState *state, XLogRecPtr pageptr, int reqLen)
/*
* Data is not in our buffer.
*
- * Every time we actually read the page, even if we looked at parts of it- * before, we need to do verification as the read_page callback might now- * be rereading data from a different source.+ * Every time we actually read the segment, even if we looked at parts of+ * it before, we need to do verification as the read_page callback might+ * now be rereading data from a different source.
*
* Whenever switching to a new WAL segment, we read the first page of the
* file and validate its header, even if that's not where the target
diff --git a/src/backend/postmaster/startup.c b/src/backend/postmaster/startup.cindex 8952676765..f35b5adf7d 100644--- a/src/backend/postmaster/startup.c+++ b/src/backend/postmaster/startup.c@@ -96,17 +96,43 @@ StartupProcShutdownHandler(SIGNAL_ARGS)
errno = save_errno;
}
+/*+ * Re-read the config file.+ *+ * If one of the critical walreceiver options has changed, flag xlog.c+ * to restart it.+ */+static void+StartupRereadConfig(void)+{+ char *conninfo = pstrdup(PrimaryConnInfo);+ char *slotname = pstrdup(PrimarySlotName);+ bool conninfoChanged;+ bool slotnameChanged;++ ProcessConfigFile(PGC_SIGHUP);++ conninfoChanged = strcmp(conninfo, PrimaryConnInfo) != 0;+ slotnameChanged = strcmp(slotname, PrimarySlotName) != 0;++ pfree(conninfo);+ pfree(slotname);++ if (conninfoChanged || slotnameChanged)+ StartupRequestWalReceiverRestart();+}+
/* Handle various signals that might be sent to the startup process */
void
HandleStartupProcInterrupts(void)
{
/*
- * Check if we were requested to re-read config file.+ * Process any requests or signals received recently.
*/
if (got_SIGHUP)
{
got_SIGHUP = false;
- ProcessConfigFile(PGC_SIGHUP);+ StartupRereadConfig();
}
/*
diff --git a/src/backend/replication/walreceiver.c b/src/backend/replication/walreceiver.cindex 779d19f1c1..0fd9886458 100644--- a/src/backend/replication/walreceiver.c+++ b/src/backend/replication/walreceiver.c@@ -671,7 +671,11 @@ WalRcvWaitForStartPosition(XLogRecPtr *startpoint, TimeLineID *startpointTLI)
walrcv->walRcvState == WALRCV_STOPPING);
if (walrcv->walRcvState == WALRCV_RESTARTING)
{
- /* we don't expect primary_conninfo to change */+ /*+ * We don't need handle changes of primary_conninfo or+ * primary_slotname here. Startup process will shutdown running+ * walreceiver in this case.+ */
*startpoint = walrcv->receiveStart;
*startpointTLI = walrcv->receiveStartTLI;
walrcv->walRcvState = WALRCV_STREAMING;
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.cindex 2c3cbbaa68..2d149dfaa5 100644--- a/src/backend/utils/misc/guc.c+++ b/src/backend/utils/misc/guc.c@@ -3717,7 +3717,7 @@ static struct config_string ConfigureNamesString[] =
},
{
- {"primary_conninfo", PGC_POSTMASTER, REPLICATION_STANDBY,+ {"primary_conninfo", PGC_SIGHUP, REPLICATION_STANDBY,
gettext_noop("Sets the connection string to be used to connect to the sending server."),
NULL,
GUC_SUPERUSER_ONLY
@@ -3728,7 +3728,7 @@ static struct config_string ConfigureNamesString[] =
},
{
- {"primary_slot_name", PGC_POSTMASTER, REPLICATION_STANDBY,+ {"primary_slot_name", PGC_SIGHUP, REPLICATION_STANDBY,
gettext_noop("Sets the name of the replication slot to use on the sending server."),
NULL
},
diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sampleindex f2e55d1bd3..31096725fd 100644--- a/src/backend/utils/misc/postgresql.conf.sample+++ b/src/backend/utils/misc/postgresql.conf.sample@@ -309,9 +309,7 @@
# These settings are ignored on a master server.
#primary_conninfo = '' # connection string to sending server
- # (change requires restart)
#primary_slot_name = '' # replication slot on sending server
- # (change requires restart)
#promote_trigger_file = '' # file name whose presence ends recovery
#hot_standby = on # "off" disallows queries during recovery
# (change requires restart)
diff --git a/src/include/access/xlog.h b/src/include/access/xlog.hindex a4485efc00..997db214cc 100644--- a/src/include/access/xlog.h+++ b/src/include/access/xlog.h@@ -319,8 +319,10 @@ extern bool CheckPromoteSignal(void);
extern void WakeupRecovery(void);
extern void SetWalWriterSleeping(bool sleeping);
+extern void StartupRequestWalReceiverRestart(void);
extern void XLogRequestWalReceiverReply(void);
+extern void ProcessStartupSigHup(void);
extern void assign_max_wal_size(int newval, void *extra);
extern void assign_checkpoint_completion_target(double newval, void *extra);
diff --git a/src/test/recovery/t/001_stream_rep.pl b/src/test/recovery/t/001_stream_rep.plindex d09ebe65a3..52585a1014 100644--- a/src/test/recovery/t/001_stream_rep.pl+++ b/src/test/recovery/t/001_stream_rep.pl@@ -3,7 +3,7 @@ use strict;
use warnings;
use PostgresNode;
use TestLib;
-use Test::More tests => 34;+use Test::More tests => 35;
# Initialize master node
my $node_master = get_new_node('master');
@@ -208,7 +208,9 @@ $node_standby_2->append_conf('postgresql.conf',
"primary_slot_name = $slotname_2");
$node_standby_2->append_conf('postgresql.conf',
"wal_receiver_status_interval = 1");
-$node_standby_2->restart;+# should be able change primary_slot_name without restart+# will wait effect in get_slot_xmins above+$node_standby_2->reload;
# Fetch xmin columns from slot's pg_replication_slots row, after waiting for
# given boolean condition to be true to ensure we've reached a quiescent state
@@ -345,6 +347,24 @@ is($xmin, '', 'xmin of cascaded slot null with hs feedback reset');
is($catalog_xmin, '',
'catalog xmin of cascaded slot still null with hs_feedback reset');
+note "check change primary_conninfo without restart";+$node_standby_2->append_conf('postgresql.conf',+ "primary_slot_name = ''");+$node_standby_2->enable_streaming($node_master);+$node_standby_2->reload;++# be sure do not streaming from cascade+$node_standby_1->stop;++my $newval = $node_master->safe_psql('postgres',+'INSERT INTO replayed(val) SELECT coalesce(max(val),0) + 1 AS newval FROM replayed RETURNING val'+);+$node_master->wait_for_catchup($node_standby_2, 'replay',+ $node_master->lsn('insert'));+my $is_replayed = $node_standby_2->safe_psql('postgres',+ qq[SELECT 1 FROM replayed WHERE val = $newval]);+is($is_replayed, qq(1), "standby_2 didn't replay master value $newval");+
# Test physical slot advancing and its durability. Create a new slot on
# the primary, not used by any of the standbys. This reserves WAL at creation.
my $phys_slot = 'phys_slot';
--
2.20.1
v10-0003-Set-wal_receiver_create_temp_slot-as-PGC_SIGHUP.patch (text/x-diff, 3.7K) download
From f5f20625b1f297cac177917c6e9b1f110ffea707 Mon Sep 17 00:00:00 2001
From: Alvaro Herrera <alvherre@alvh.no-ip.org>
Date: Wed, 25 Mar 2020 20:54:27 -0300
Subject: [PATCH v10 3/3] Set wal_receiver_create_temp_slot as PGC_SIGHUP
.. using the new infrastructure
---
doc/src/sgml/config.sgml | 6 +++++-
src/backend/postmaster/startup.c | 10 +++++++++-
src/backend/utils/misc/guc.c | 2 +-
src/backend/utils/misc/postgresql.conf.sample | 1 -
4 files changed, 15 insertions(+), 4 deletions(-)
diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgmlindex 4d17dafa7e..c5160fe907 100644--- a/doc/src/sgml/config.sgml+++ b/doc/src/sgml/config.sgml@@ -4173,7 +4173,11 @@ ANY <replaceable class="parameter">num_sync</replaceable> ( <replaceable class="
Specifies whether a WAL receiver should create a temporary replication
slot on the remote instance when no permanent replication slot to use
has been configured (using <xref linkend="guc-primary-slot-name"/>).
- The default is off. This parameter can only be set at server start.+ The default is off. This parameter can only be set in the + <filename>postgresql.conf</filename> file or on the server command line.+ </para>+ <para>+ The WAL receiver is restarted after an update of <varname>wal_receiver_create_temp_slot</varname>.
</para>
</listitem>
</varlistentry>
diff --git a/src/backend/postmaster/startup.c b/src/backend/postmaster/startup.cindex f35b5adf7d..fd9ac35dac 100644--- a/src/backend/postmaster/startup.c+++ b/src/backend/postmaster/startup.c@@ -107,18 +107,26 @@ StartupRereadConfig(void)
{
char *conninfo = pstrdup(PrimaryConnInfo);
char *slotname = pstrdup(PrimarySlotName);
+ bool tempSlot = wal_receiver_create_temp_slot;
bool conninfoChanged;
bool slotnameChanged;
+ bool tempSlotChanged = false;
ProcessConfigFile(PGC_SIGHUP);
conninfoChanged = strcmp(conninfo, PrimaryConnInfo) != 0;
slotnameChanged = strcmp(slotname, PrimarySlotName) != 0;
+ /*+ * wal_receiver_create_temp_slot is used only when we have no slot+ * configured. We do not need to track this change if it has no effect.+ */+ if (!slotnameChanged && strcmp(PrimarySlotName, "") == 0)+ tempSlotChanged = tempSlot != wal_receiver_create_temp_slot;
pfree(conninfo);
pfree(slotname);
- if (conninfoChanged || slotnameChanged)+ if (conninfoChanged || slotnameChanged || tempSlotChanged)
StartupRequestWalReceiverRestart();
}
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.cindex 2d149dfaa5..53665971f5 100644--- a/src/backend/utils/misc/guc.c+++ b/src/backend/utils/misc/guc.c@@ -2050,7 +2050,7 @@ static struct config_bool ConfigureNamesBool[] =
},
{
- {"wal_receiver_create_temp_slot", PGC_POSTMASTER, REPLICATION_STANDBY,+ {"wal_receiver_create_temp_slot", PGC_SIGHUP, REPLICATION_STANDBY,
gettext_noop("Sets whether a WAL receiver should create a temporary replication slot if no permanent slot is configured."),
},
&wal_receiver_create_temp_slot,
diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sampleindex 31096725fd..f01e43b818 100644--- a/src/backend/utils/misc/postgresql.conf.sample+++ b/src/backend/utils/misc/postgresql.conf.sample@@ -321,7 +321,6 @@
# -1 allows indefinite delay
#wal_receiver_create_temp_slot = off # Create temp slot if primary_slot_name
# is not set.
- # (change requires restart)
#wal_receiver_status_interval = 10s # send replies at least this often
# 0 disables
#hot_standby_feedback = off # send info from standby to prevent
--
2.20.1
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Reply to all the recipients using the --to and --cc options:
reply via email
To: pgsql-hackers@postgresql.org
Cc: alvherre@2ndquadrant.com, sk@zsrv.org, michael@paquier.xyz, tomas.vondra@2ndquadrant.com, horikyota.ntt@gmail.com, andres@anarazel.de, david@pgmasters.net, peter.eisentraut@2ndquadrant.com
Subject: Re: allow online change primary_conninfo
In-Reply-To: <20200326000812.GA18798@alvherre.pgsql>
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
This inbox is served by DDX for PostgreSQL; see mirroring instructions
for how to clone and mirror all data and code used for this inbox