diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index 5d1c90282f9..5d45b6f7cba 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -4124,6 +4124,26 @@ ANY num_sync (
+ wal_receiver_create_temp_slot (boolean)
+
+ wal_receiver_create_temp_slot configuration parameter
+
+
+
+
+ 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 ).
+ 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.
+
+
+
+
wal_receiver_status_interval (integer)
diff --git a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
index b731d3fd04e..e4fd1f9bb6f 100644
--- a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
+++ b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
@@ -834,6 +834,10 @@ libpqrcv_create_slot(WalReceiverConn *conn, const char *slotname,
break;
}
}
+ else
+ {
+ appendStringInfoString(&cmd, " PHYSICAL RESERVE_WAL");
+ }
res = libpqrcv_PQexec(conn->streamConn, cmd.data);
pfree(cmd.data);
diff --git a/src/backend/replication/walreceiver.c b/src/backend/replication/walreceiver.c
index 77360f1524b..b4641143339 100644
--- a/src/backend/replication/walreceiver.c
+++ b/src/backend/replication/walreceiver.c
@@ -73,6 +73,7 @@
/* GUC variables */
+bool wal_receiver_create_temp_slot;
int wal_receiver_status_interval;
int wal_receiver_timeout;
bool hot_standby_feedback;
@@ -169,6 +170,7 @@ WalReceiverMain(void)
char conninfo[MAXCONNINFO];
char *tmp_conninfo;
char slotname[NAMEDATALEN];
+ bool is_temp_slot;
XLogRecPtr startpoint;
TimeLineID startpointTLI;
TimeLineID primaryTLI;
@@ -230,6 +232,7 @@ WalReceiverMain(void)
walrcv->ready_to_display = false;
strlcpy(conninfo, (char *) walrcv->conninfo, MAXCONNINFO);
strlcpy(slotname, (char *) walrcv->slotname, NAMEDATALEN);
+ is_temp_slot = walrcv->is_temp_slot;
startpoint = walrcv->receiveStart;
startpointTLI = walrcv->receiveStartTLI;
@@ -345,6 +348,44 @@ 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
+ * 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)
+ {
+ bool changed = false;
+
+ if (wal_receiver_create_temp_slot)
+ {
+ snprintf(slotname, sizeof(slotname),
+ "pg_walreceiver_%d", walrcv_get_backend_pid(wrconn));
+
+ 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);
+ }
+ }
+
/*
* Start streaming.
*
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 62285792eca..e5f8a1301fa 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1969,6 +1969,15 @@ static struct config_bool ConfigureNamesBool[] =
NULL, NULL, NULL
},
+ {
+ {"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,
+ true,
+ NULL, NULL, NULL
+ },
+
/* End-of-list marker */
{
{NULL, 0, 0, NULL, NULL}, NULL, false, NULL, NULL, NULL
diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample
index 087190ce638..e1048c0047b 100644
--- a/src/backend/utils/misc/postgresql.conf.sample
+++ b/src/backend/utils/misc/postgresql.conf.sample
@@ -321,6 +321,7 @@
#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_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/replication/walreceiver.h b/src/include/replication/walreceiver.h
index 172cfa28629..e08afc6548f 100644
--- a/src/include/replication/walreceiver.h
+++ b/src/include/replication/walreceiver.h
@@ -23,6 +23,7 @@
#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;
@@ -121,6 +122,12 @@ typedef struct
*/
char slotname[NAMEDATALEN];
+ /*
+ * If it's a temporary replication slot, it needs to be recreated when
+ * connecting.
+ */
+ bool is_temp_slot;
+
/* set true once conninfo is ready to display (obfuscated pwds etc) */
bool ready_to_display;