From: Alvaro Herrera Date: Wed, 25 Mar 2020 20:48:44 -0300 Subject: [PATCH v11 3/3] Rework wal_receiver_create_temp_slot using new infrastructure --- doc/src/sgml/config.sgml | 10 ++--- src/backend/access/transam/xlog.c | 3 +- src/backend/postmaster/startup.c | 10 ++++- src/backend/replication/walreceiver.c | 40 +++++-------------- src/backend/replication/walreceiverfuncs.c | 28 ++++++++++--- src/backend/utils/misc/guc.c | 2 +- src/backend/utils/misc/postgresql.conf.sample | 3 +- src/include/access/xlog.h | 1 + src/include/replication/walreceiver.h | 4 +- 9 files changed, 55 insertions(+), 46 deletions(-) diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml index 1cf88e953d..c5160fe907 100644 --- a/doc/src/sgml/config.sgml +++ b/doc/src/sgml/config.sgml @@ -4173,11 +4173,11 @@ ANY num_sync ( ). - 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 postgresql.conf - 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 in the + postgresql.conf file or on the server command line. + + + The WAL receiver is restarted after an update of wal_receiver_create_temp_slot. diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index bbf8d4eee5..2ecb319438 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; @@ -12157,7 +12158,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/postmaster/startup.c b/src/backend/postmaster/startup.c index 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/replication/walreceiver.c b/src/backend/replication/walreceiver.c index b471a49d12..0aa0c52c49 100644 --- a/src/backend/replication/walreceiver.c +++ b/src/backend/replication/walreceiver.c @@ -80,7 +80,6 @@ /* GUC variables */ -bool wal_receiver_create_temp_slot; int wal_receiver_status_interval; int wal_receiver_timeout; bool hot_standby_feedback; @@ -355,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.c index 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.c index c0b2b75407..53665971f5 100644 --- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -2054,7 +2054,7 @@ static struct config_bool ConfigureNamesBool[] = 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.sample index c4f2f881c9..f01e43b818 100644 --- a/src/backend/utils/misc/postgresql.conf.sample +++ b/src/backend/utils/misc/postgresql.conf.sample @@ -319,7 +319,8 @@ #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. #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.h index 42c4df0262..997db214cc 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.h index 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 --ibTvN161/egqYuK8--