Streaming Replication Disconnection Behavior under recovery_min_apply_delay Configuration - Mailing list pgsql-general
From | Riku Kashiwaki (Fujitsu) |
---|---|
Subject | Streaming Replication Disconnection Behavior under recovery_min_apply_delay Configuration |
Date | |
Msg-id | OS3PR01MB63229C46662074838546DF589064A@OS3PR01MB6322.jpnprd01.prod.outlook.com Whole thread Raw |
List | pgsql-general |
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 ALTERSET 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 afterreceiving 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 equivalentto 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 ofWAL 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); }
pgsql-general by date: