On Mon, Apr 6, 2020 at 1:52 AM Masahiko Sawada <
masahiko.saw...@2ndquadrant.com> wrote:

> On Mon, 6 Apr 2020 at 14:04, Andres Freund <and...@anarazel.de> wrote:
> >
> > commit 48c9f4926562278a2fd2b85e7486c6d11705f177
> > Author: Simon Riggs <si...@2ndquadrant.com>
> > Date:   2017-12-29 14:30:33 +0000
> >
> >     Fix race condition when changing synchronous_standby_names
> >
> >     A momentary window exists when synchronous_standby_names
> >     changes that allows commands issued after the change to
> >     continue to act as async until the change becomes visible.
> >     Remove the race by using more appropriate test in syncrep.c
> >
> >     Author: Asim Rama Praveen and Ashwin Agrawal
> >     Reported-by: Xin Zhang, Ashwin Agrawal, and Asim Rama Praveen
> >     Reviewed-by: Michael Paquier, Masahiko Sawada
> >
> > As far as I can tell there was no discussion about the added contention
> > due this change in the relevant thread [1].
> >
> > The default configuration has an empty synchronous_standby_names. Before
> > this change we'd fall out of SyncRepWaitForLSN() before acquiring
> > SyncRepLock in exlusive mode. Now we don't anymore.
> >
> >
> > I'm really not ok with unneccessarily adding an exclusive lock
> > acquisition to such a crucial path.
> >
>
> I think we can acquire SyncRepLock in share mode once to check
> WalSndCtl->sync_standbys_defined and if it's true then check it again
> after acquiring it in exclusive mode. But it in turn ends up with
> adding one extra LWLockAcquire and LWLockRelease in sync rep path.
>

How about we change it to this ?

diff --git a/src/backend/replication/syncrep.c
b/src/backend/replication/syncrep.c
index ffd5b31eb2..cdb82a8b28 100644
--- a/src/backend/replication/syncrep.c
+++ b/src/backend/replication/syncrep.c
@@ -165,8 +165,11 @@ SyncRepWaitForLSN(XLogRecPtr lsn, bool commit)
        /*
         * Fast exit if user has not requested sync replication.
         */
-       if (!SyncRepRequested())
-               return;
+       if (!SyncRepRequested() || !SyncStandbysDefined())
+       {
+               if (!WalSndCtl->sync_standbys_defined)
+                       return;
+       }

        Assert(SHMQueueIsDetached(&(MyProc->syncRepLinks)));
        Assert(WalSndCtl != NULL);

Bring back the check which existed based on GUC but instead of just blindly
returning based on just GUC not being set, check
WalSndCtl->sync_standbys_defined. Thoughts?

Reply via email to