Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1rfd6p-001GQy-Vp for pgsql-hackers@arkaria.postgresql.org; Thu, 29 Feb 2024 09:53:48 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.94.2) (envelope-from ) id 1rfd6o-0022Qj-GY for pgsql-hackers@arkaria.postgresql.org; Thu, 29 Feb 2024 09:53:46 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1rfd6o-0022Qb-5n for pgsql-hackers@lists.postgresql.org; Thu, 29 Feb 2024 09:53:46 +0000 Received: from mail-oa1-x32.google.com ([2001:4860:4864:20::32]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.94.2) (envelope-from ) id 1rfd6l-002233-DE for pgsql-hackers@postgresql.org; Thu, 29 Feb 2024 09:53:46 +0000 Received: by mail-oa1-x32.google.com with SMTP id 586e51a60fabf-22008177fbeso369940fac.2 for ; Thu, 29 Feb 2024 01:53:43 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1709200422; x=1709805222; darn=postgresql.org; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:from:to:cc:subject:date :message-id:reply-to; bh=ujB3VYS80UFwNC5jkJ/xvlElZONHH12v1pxqmNJU22A=; b=hJCrqp88HIzu/e8oh+ZC0ZGRVzl9iJsd2tEqpBV3zmBro7Dz8irgR7hl38NKqUZ684 QARTBGDiiOaJrrPJhmmXa5r38HVHh7YxetehtDW/ruJjXm6N9bfJZl663f62MmzL4PSb pHn5yiB/KAyv0RtWh2HZ3KlknqA1yHeKP9tNgR6dyPsIxh4edWEwHDejDL1/VJb0Ieli UnvOaEGXic5RwW/8KCkBjGdy8VUQ1yfeoel5v7t+NHIGtzM4ZVCvWci5Tpr0alKMAoIY LPaBMhPnAVwb1ufhs5ROHxxU6bS1vkIXbN7VEHyZQt09YMaZvEZDVRMvqfL7VHhlM8Vk CKMQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1709200422; x=1709805222; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=ujB3VYS80UFwNC5jkJ/xvlElZONHH12v1pxqmNJU22A=; b=nqVC2WHUfdhrJXYmFP8PTDZeKtmfLbK11fGZZ0IQ3xfJnjX6uUL3bzwsthgO3YPZNU aprKCI1hajuGlHaiXCvkSVAt6/5MyBXXf50MyyJsfVCQrF5FxYbGsU1oNhrofcvwHBsM tAobBPHeEVTe3ZHE06NQ4b1g/b/FV7ZaDtjECF1bfXqZiA6mcCwT8ITygIxQbzbMl4Im dVx35a+u+mYu7cZQeYgEK2m/CnvSWnQA+7ctU7fJwPbvI2BFJhayxhmZe+XLmwmN7/rZ UMr4pkhA6VyaWx8r9dqIuqDUdcclMsdrKJUrr2FkY4RZz+2CPZjd/UPEtmdsDi/GzTmR xBLQ== X-Forwarded-Encrypted: i=1; AJvYcCWwxUv//qyVpUwRl0Dl4Iplh7GZ1F+jIfgpx4EjQnBRhdL0SPflmW4NC3Z5Q/ClmTkRQBU8PZvRQ5eAmay929O/ucHkXW2kMcBpSIrJ X-Gm-Message-State: AOJu0YzRxnMSOgBPdTbnoKll6EqO2SvR6zNWVV2NrpTF5DwDflb+0B5Z hBy42+TXkDp+9rME9MtauxWliifPiHVWxQH2QJRVCS72iiUvcFLYbVuomDe2lDTmEQyzssCCyXr LGrkWjNvleWoUYNgEgJuchjAsRxE= X-Google-Smtp-Source: AGHT+IEiOz2XUJrlW0WQqZwuPMopxB9pICK2lu1sN3Tf/ZeoelrMSRWV3O4o6oUPfdah9LZQypU7vmr4xOcoNRNeXMc= X-Received: by 2002:a05:6871:5d3:b0:21f:df8d:50 with SMTP id v19-20020a05687105d300b0021fdf8d0050mr1379935oan.56.1709200421836; Thu, 29 Feb 2024 01:53:41 -0800 (PST) MIME-Version: 1.0 References: In-Reply-To: From: Amit Kapila Date: Thu, 29 Feb 2024 15:23:30 +0530 Message-ID: Subject: Re: Synchronizing slots from primary to standby To: Peter Smith Cc: "Zhijie Hou (Fujitsu)" , shveta malik , Masahiko Sawada , Ajin Cherian , Dilip Kumar , Nisha Moond , "Hayato Kuroda (Fujitsu)" , Bertrand Drouvot , Bharath Rupireddy , Peter Eisentraut , Bruce Momjian , Ashutosh Sharma , Andres Freund , pgsql-hackers , Alvaro Herrera Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk On Thu, Feb 29, 2024 at 8:29=E2=80=AFAM Peter Smith = wrote: > > On Wed, Feb 28, 2024 at 1:23=E2=80=AFPM Zhijie Hou (Fujitsu) > wrote: > > > > On Tuesday, February 27, 2024 3:18 PM Peter Smith wrote: > ... > > > 20. > > > +# > > > +# | ----> standby1 (primary_slot_name =3D sb1_slot) # | ----> standb= y2 > > > +(primary_slot_name =3D sb2_slot) # primary ----- | # | ----> subscri= ber1 > > > +(failover =3D true) # | ----> subscriber2 (failover =3D false) > > > > > > In the diagram, the "--->" means a mixture of physical standbys and l= ogical > > > pub/sub replication. Maybe it can be a bit clearer? > > > > > > SUGGESTION > > > > > > # primary (publisher) > > > # > > > # (physical standbys) > > > # | ----> standby1 (primary_slot_name =3D sb1_slot) > > > # | ----> standby2 (primary_slot_name =3D sb2_slot) > > > # > > > # (logical replication) > > > # | ----> subscriber1 (failover =3D true, slot_name =3D lsub1_slo= t) > > > # | ----> subscriber2 (failover =3D false, slot_name =3D lsub2_sl= ot) > > > > > > > I think one can distinguish it based on the 'standby' and 'subscriber' = as well, because > > 'standby' normally refer to physical standby while the other refer to l= ogical. > > I think Peter's suggestion will make the setup clear. > > Ok, but shouldn't it at least include info about the logical slot > names associated with the subscribers (slot_name =3D lsub1_slot, > slot_name =3D lsub2_slot) like suggested above? > > =3D=3D=3D=3D=3D=3D > > Here are some more review comments for v100-0001 > > =3D=3D=3D=3D=3D=3D > doc/src/sgml/config.sgml > > 1. > + > + Lists the streaming replication standby server slot names that l= ogical > + WAL sender processes will wait for. Logical WAL sender processes= will > + send decoded changes to plugins only after the specified replica= tion > + slots confirm receiving WAL. This guarantees that logical replic= ation > + slots with failover enabled do not consume changes until those c= hanges > + are received and flushed to corresponding physical standbys. If = a > + logical replication connection is meant to switch to a physical = standby > + after the standby is promoted, the physical replication slot for= the > + standby should be listed here. Note that logical replication wil= l not > + proceed if the slots specified in the standby_slot_names do > not exist or > + are invalidated. > + > > Is that note ("Note that logical replication will not proceed if the > slots specified in the standby_slot_names do not exist or are > invalidated") meant only for subscriptions marked for 'failover' or > any subscription? Maybe wording can be modified to help clarify it? > I think it is implicit that here we are talking about failover slots. I think clarifying again the same could be repetitive considering the previous sentence: "This guarantees that logical replication slots with failover enabled do not consume .." have mentioned it. > =3D=3D=3D=3D=3D=3D > src/backend/replication/slot.c > > 2. > +/* > + * A helper function to validate slots specified in GUC standby_slot_nam= es. > + */ > +static bool > +validate_standby_slots(char **newval) > +{ > + char *rawname; > + List *elemlist; > + bool ok; > + > + /* Need a modifiable copy of string */ > + rawname =3D pstrdup(*newval); > + > + /* Verify syntax and parse string into a list of identifiers */ > + ok =3D SplitIdentifierString(rawname, ',', &elemlist); > + > + if (!ok) > + { > + GUC_check_errdetail("List syntax is invalid."); > + } > + > + /* > + * If the replication slots' data have been initialized, verify if the > + * specified slots exist and are logical slots. > + */ > + else if (ReplicationSlotCtl) > + { > + foreach_ptr(char, name, elemlist) > + { > + ReplicationSlot *slot; > + > + slot =3D SearchNamedReplicationSlot(name, true); > + > + if (!slot) > + { > + GUC_check_errdetail("replication slot \"%s\" does not exist", > + name); > + ok =3D false; > + break; > + } > + > + if (!SlotIsPhysical(slot)) > + { > + GUC_check_errdetail("\"%s\" is not a physical replication slot", > + name); > + ok =3D false; > + break; > + } > + } > + } > + > + pfree(rawname); > + list_free(elemlist); > + return ok; > +} > > 2a. > I didn't mention this previously because I thought this function was > not going to change anymore, but since Bertrand suggested some changes > [1], I will say IMO the { } are fine here for the single statement, > but I think it will be better to rearrange this code to be like below. > Having a 2nd NOP 'else' gives a much better place where you can put > your ReplicationSlotCtl comment. > > if (!ok) > { > GUC_check_errdetail("List syntax is invalid."); > } > else if (!ReplicationSlotCtl) > { > ReplicationSlotCtl is NULL> > } > else > { > foreach_ptr ... > } > +1. This will make the code and reasoning to skip clear. Few additional comments on the latest patch: =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D 1. static XLogRecPtr WalSndWaitForWal(XLogRecPtr loc) { ... + if (!XLogRecPtrIsInvalid(RecentFlushPtr) && loc <=3D RecentFlushPtr && + (!replication_active || StandbyConfirmedFlush(loc, WARNING))) + { + /* + * Fast path to avoid acquiring the spinlock in case we already know + * we have enough WAL available and all the standby servers have + * confirmed receipt of WAL up to RecentFlushPtr. This is particularly + * interesting if we're far behind. + */ return RecentFlushPtr; + } ... ... + * Wait for WALs to be flushed to disk only if the postmaster has not + * asked us to stop. + */ + if (loc > RecentFlushPtr && !got_STOPPING) + wait_event =3D WAIT_EVENT_WAL_SENDER_WAIT_FOR_WAL; + + /* + * Check if the standby slots have caught up to the flushed position. + * It is good to wait up to RecentFlushPtr and then let it send the + * changes to logical subscribers one by one which are already covered + * in RecentFlushPtr without needing to wait on every change for + * standby confirmation. Note that after receiving the shutdown signal, + * an ERROR is reported if any slots are dropped, invalidated, or + * inactive. This measure is taken to prevent the walsender from + * waiting indefinitely. + */ + else if (replication_active && + !StandbyConfirmedFlush(RecentFlushPtr, WARNING)) + { + wait_event =3D WAIT_EVENT_WAIT_FOR_STANDBY_CONFIRMATION; + wait_for_standby =3D true; + } + else + { + /* Already caught up and doesn't need to wait for standby_slots. */ break; + } ... } Can we try to move these checks into a separate function that returns a boolean and has an out parameter as wait_event? 2. How about naming StandbyConfirmedFlush() as StandbySlotsAreCaughtup? --=20 With Regards, Amit Kapila.