public inbox for [email protected]  
help / color / mirror / Atom feed
From: Riku Kashiwaki (Fujitsu) <[email protected]>
To: '[email protected]' <[email protected]>
Subject: Streaming Replication Disconnection Behavior under recovery_min_apply_delay Configuration
Date: Tue, 27 May 2025 05:04:49 +0000
Message-ID: <OS3PR01MB63229C46662074838546DF589064A@OS3PR01MB6322.jpnprd01.prod.outlook.com> (raw)

I would like to know the behavior when disconnecting streaming replication.
An attempt was made to disconnect streaming replication from a standby server during streaming replication by using the ALTER SET command and setting primary _conninfo to an empty string.
However, we have observed that if recovery_min_apply_delay is set and primary_conninfo is set to an empty string + reloaded, with some WAL remaining that has been sent to the standby but not yet applied, replication will not break.

Specifically, the following procedures are used.
environment: Postgres16
 recovery_min_apply_delay= set to 5min
 One Primary, One Standby Streaming Replication Configuration
① primary_conninfo set to an empty string
 #ALTER SET primary_conninfo=''"
② Reload and reload the configuration file
 #pg_ctl reload
③ Ensure replication is not terminated
 #psql -d postgres -p 27500 -c "select * from pg_stat_replication"
   pid | usesysid | usename | application_name | client_addr | client_hostname | client_port | backend_start | backend_xmin | state | sent_lsn | write_lsn | flush_lsn | replay_lsn | write_lag | flush_lag | replay_lag | sync_priority | sync_state | reply_time
---------+----------+---------+------------------+-------------+-----------------+-------------+-------------------------------+--------------+-----------+------------+------------+------------+------------+-----------------+-----------------+-----------------+---------------+------------+-------------------------------
 3707259 | 10 | **** | walreceiver | | | -1 | 2025-**-** **:**:**.*** | | streaming | 0/190047E0 | 0/190047E0 | 0/190047E0 | 0/19002840 | 00:00:00.000073 | 00:00:00.000261 | 00:01:16.999715 | 0 | async | 2025-**-** **:**:**.**
(1 line)

④ Verify replication is finished after 5 minutes
 #psql -d postgres -p 27500 -c "select * from pg_stat_replication"
   pid | usesysid | usename | application_name | client_addr | client_hostname | client_port | backend_start | backend_xmin | state | sent_lsn | write_lsn | flush_lsn | replay_lsn | write_lag | flush_lag | replay_lag | sync_priority | sync_state | reply_time
---------+----------+---------+------------------+-------------+-----------------+-------------+-------------------------------+--------------+-----------+------------+------------+------------+------------+-----------------+-----------------+-----------------+---------------+------------+-------------------------------
(0 lines)
As shown above, walreceiver does not terminate until the time specified by recovery_min_apply_delay has elapsed, even after receiving WAL from the primary.
When you stop the strep configuration, you don't need to make the data consistent with the primary (make the DB state equivalent to the primary), and it seems natural that the strep configuration should be disconnected immediately.
Why doesn't the walreceiver process exit until WAL has been applied?

Also, in the source code of walreceiver (Lines 452 to 491 of walreceiver.c), there is a process to wait for completion of WAL reception (* 1), but there is no description of the action to wait for walreceiver to terminate if unapplied WAL remains.
I would appreciate it if you could tell me where you are waiting for walreceiver to exit.


*1 Details
https://github.com/postgres/postgres/blob/master/src/backend/replication/walreceiver.c

(walreceiver.c)
[Processing to loop until walreceiver ends]
 Defines the endofwal flag used to terminate the walreceiver.
			/* Loop until end-of-streaming or error */
			for (;;)
			{
				char	 *buf;
				int			len;
				bool		endofwal = false;
				pgsocket	wait_fd = PGINVALID_SOCKET;
				int			rc;
				TimestampTz nextWakeup;
				long		nap;


[Continuing/terminating walreceiver with reference to the length of unreceived WAL (len)]
 len is assigned the return value of the walrcv_receive function (★).
 walrcv_receive returns the length of WAL that has not yet been received from the primary (or -1 if it has).


			/* See if we can read data immediately */
				len = walrcv_receive(wrconn, &buf, &wait_fd); ★
				if (len != 0)
				{
					/*
					 * Process the received data, and any subsequent data we
					 * can read without blocking.
					 */
					for (;;)
					{
						if (len > 0)
						{
							/*
							 * Something was received from primary, so adjust
							 * the ping and terminate wakeup times.
							 */
							now = GetCurrentTimestamp();
							WalRcvComputeNextWakeup(WALRCV_WAKEUP_TERMINATE,
													now);
							WalRcvComputeNextWakeup(WALRCV_WAKEUP_PING, now);
							XLogWalRcvProcessMsg(buf[0], &buf[1], len - 1,
												 startpointTLI);
						}
						else if (len == 0)
							break;
						else if (len < 0)
						{
							ereport(LOG,
									(errmsg("replication terminated by primary server"),
									 errdetail("End of WAL reached on timeline %u at %X/%X.",
											   startpointTLI,
											   LSN_FORMAT_ARGS(LogstreamResult.Write))));
							endofwal = true;
							break;
						}
						len = walrcv_receive(wrconn, &buf, &wait_fd);
					}








reply

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: [email protected]
  Cc: [email protected]
  Subject: Re: Streaming Replication Disconnection Behavior under recovery_min_apply_delay Configuration
  In-Reply-To: <OS3PR01MB63229C46662074838546DF589064A@OS3PR01MB6322.jpnprd01.prod.outlook.com>

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox