v6-0002-Introduce-smart-shutdown-for-logical-walsender.patch

application/octet-stream

Filename: v6-0002-Introduce-smart-shutdown-for-logical-walsender.patch
Type: application/octet-stream
Part: 1
Message: RE: Exit walsender before confirming remote flush in logical replication

Patch

Same data as JSON: GET /api/v1/attachments/:id/patch the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes. API reference →
Format: format-patch
Series: patch v6-0002
Subject: Introduce smart shutdown for logical walsender
File+
src/backend/postmaster/postmaster.c 4 0
src/backend/replication/walsender.c 32 5
src/include/replication/walsender.h 9 0
src/include/replication/walsender_private.h 7 0
From 74fc0770c68cbf5605264907ca8cd328f675f9ec Mon Sep 17 00:00:00 2001
From: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Date: Fri, 3 Feb 2023 11:17:26 +0000
Subject: [PATCH v6 2/2] Introduce smart shutdown for logical walsender

---
 src/backend/postmaster/postmaster.c         |  4 +++
 src/backend/replication/walsender.c         | 37 ++++++++++++++++++---
 src/include/replication/walsender.h         |  9 +++++
 src/include/replication/walsender_private.h |  7 ++++
 4 files changed, 52 insertions(+), 5 deletions(-)

diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index f92dbc2270..8a7d1d4efa 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -3813,6 +3813,10 @@ PostmasterStateMachine(void)
 				if (CheckpointerPID != 0)
 				{
 					signal_child(CheckpointerPID, SIGUSR2);
+					if (Shutdown >= FastShutdown)
+						WalSndChangeShutdownState(WALSNDSHUTDOWNSTATE_FASTSHUTDOWN);
+					else
+						WalSndChangeShutdownState(WALSNDSHUTDOWNSTATE_SMARTSHUTDOWN);
 					pmState = PM_SHUTDOWN;
 				}
 				else
diff --git a/src/backend/replication/walsender.c b/src/backend/replication/walsender.c
index 25a052adfc..820d74c5a7 100644
--- a/src/backend/replication/walsender.c
+++ b/src/backend/replication/walsender.c
@@ -260,6 +260,16 @@ static bool TransactionIdInRecentPast(TransactionId xid, uint32 epoch);
 static void WalSndSegmentOpen(XLogReaderState *state, XLogSegNo nextSegNo,
 							  TimeLineID *tli_p);
 
+#define SHUTDOWN_CONDTION_FOR_LOGICAL(send_data)					\
+	((send_data) == XLogSendLogical &&								\
+	 (WalSndCtl->Shutdown == WALSNDSHUTDOWNSTATE_FASTSHUTDOWN ||	\
+	  (WalSndCtl->Shutdown == WALSNDSHUTDOWNSTATE_SMARTSHUTDOWN &&	\
+	   !pq_is_send_pending())))
+
+#define SHUTDOWN_CONDTION_FOR_PHYSICAL(send_data)		\
+	((send_data) == XLogSendPhysical &&					\
+	 sentPtr == replicatedPtr && !pq_is_send_pending())
+
 
 /* Initialize walsender process before entering the main command loop */
 void
@@ -3122,13 +3132,18 @@ WalSndDone(WalSndSendDataCallback send_data)
 	/*
 	 * Exit if we are in the convenient time.
 	 *
-	 * When we are logical replication mode, we don't have to wait that all
-	 * sent data to be flushed on the subscriber because we cannot support
-	 * clean switchover for it.
+	 * When we are logical replication mode, the condition for shutdown is
+	 * changed based on the shutdown mode.
+	 *
+	 * For smart shutdown mode, we confirm that there is no pending data
+	 * in the output buffer.
+	 *
+	 * For fast shutdown mode, we don't have to wait that all sent data to be
+	 * flushed on the subscriber.
 	 */
 	if (WalSndCaughtUp &&
-		(send_data == XLogSendLogical ||
-		 (sentPtr == replicatedPtr && !pq_is_send_pending())))
+		(SHUTDOWN_CONDTION_FOR_LOGICAL(send_data) ||
+		 SHUTDOWN_CONDTION_FOR_PHYSICAL(send_data)))
 	{
 		QueryCompletion qc;
 
@@ -3867,3 +3882,15 @@ LagTrackerRead(int head, XLogRecPtr lsn, TimestampTz now)
 	Assert(time != 0);
 	return now - time;
 }
+
+/*
+ * Change the indicator for shutdown mode.
+ *
+ * This should be called by postmaster
+ */
+void
+WalSndChangeShutdownState(WalSndShutdownState state)
+{
+	Assert(!IsUnderPostmaster);
+	WalSndCtl->Shutdown = state;
+}
diff --git a/src/include/replication/walsender.h b/src/include/replication/walsender.h
index 52bb3e2aae..97a31e1613 100644
--- a/src/include/replication/walsender.h
+++ b/src/include/replication/walsender.h
@@ -24,6 +24,13 @@ typedef enum
 	CRS_USE_SNAPSHOT
 } CRSSnapshotAction;
 
+typedef enum WalSndShutdownState
+{
+	WALSNDSHUTDOWNSTATE_NOSHUTDOWN = 0,
+	WALSNDSHUTDOWNSTATE_SMARTSHUTDOWN,
+	WALSNDSHUTDOWNSTATE_FASTSHUTDOWN,
+} WalSndShutdownState;
+
 /* global state */
 extern PGDLLIMPORT bool am_walsender;
 extern PGDLLIMPORT bool am_cascading_walsender;
@@ -48,6 +55,8 @@ extern void WalSndWaitStopping(void);
 extern void HandleWalSndInitStopping(void);
 extern void WalSndRqstFileReload(void);
 
+extern void WalSndChangeShutdownState(WalSndShutdownState state);
+
 /*
  * Remember that we want to wakeup walsenders later
  *
diff --git a/src/include/replication/walsender_private.h b/src/include/replication/walsender_private.h
index 5310e054c4..6171c16cb2 100644
--- a/src/include/replication/walsender_private.h
+++ b/src/include/replication/walsender_private.h
@@ -105,6 +105,13 @@ typedef struct
 	 */
 	bool		sync_standbys_defined;
 
+	/*
+	 * Indicator for shutdown mode. Basically it is set to zero, which means
+	 * that shutdown has not been requested yet. The value will be changed
+	 * olny once by postmaster.
+	 */
+	int			Shutdown;
+
 	WalSnd		walsnds[FLEXIBLE_ARRAY_MEMBER];
 } WalSndCtlData;
 
-- 
2.27.0