Re: Implement waiting for wal lsn replay: reloaded
Alexander Korotkov <aekorotkov@gmail.com>
Attachments
- v5-0001-Use-barrier-semantics-when-reading-writing-writte.patch (application/octet-stream) patch v5-0001
- v5-0002-Fix-memory-ordering-in-WAIT-FOR-LSN-wakeup-mechan.patch (application/octet-stream) patch v5-0002
- v5-0003-Remove-redundant-WAIT-FOR-LSN-caller-side-pre-che.patch (application/octet-stream) patch v5-0003
- v5-0004-Use-replay-position-as-floor-for-WAIT-FOR-LSN-sta.patch (application/octet-stream) patch v5-0004
- v5-0005-Wake-standby_write-standby_flush-waiters-from-the.patch (application/octet-stream) patch v5-0005
- v5-0006-Improve-WAIT-FOR-LSN-test-coverage.patch (application/octet-stream) patch v5-0006
- v5-0007-Document-that-WAIT-FOR-LSN-is-timeline-blind.patch (application/octet-stream) patch v5-0007
On Fri, Apr 10, 2026 at 9:13 AM Xuneng Zhou <xunengzhou@gmail.com> wrote:
>
> On Fri, Apr 10, 2026 at 11:59 AM Xuneng Zhou <xunengzhou@gmail.com> wrote:
> >
> > On Fri, Apr 10, 2026 at 12:18 AM Andres Freund <andres@anarazel.de> wrote:
> > >
> > > On 2026-04-09 18:21:24 +0300, Alexander Korotkov wrote:
> > > > I've assembled all the pending patches together.
> > > > 0001 adds memory barrier to GetWalRcvWriteRecPtr() as suggested by
> > > > Andres off-list.
> > >
> > > I'd make it a pg_atomic_read_membarrier_u64().
> > >
> > >
> > > > 0002 is basically [1] by Xuneng, but revised given we have a memory
> > > > barrier in 0001, and my proposal to do ResetLatch() unconditionally
> > > > similar to our other Latch-based loops.
> > > > 0003 and 0004 are [2] by Xuneng.
> > > > 0005 is [3] by Xuneng.
> > > >
> > > > I'm going to add them to Commitfest to run CI over them, and have a
> > > > closer look over them tomorrow.
> > >
> > > Briefly skimming the patches, none makes the writes to writtenUpto use
> > > something bearing barrier semantics. I'd just make both of them a
> > > pg_atomic_write_membarrier_u64().
> > >
> >
> > Makes sense to me. Done.
> >
> > > I think this also needs a few more tests, e.g. for the scenario that
> > > 29e7dbf5e4d fixed. I think it'd also be good to do some testing for
> > > off-by-one dangers. E.g. making sure that we don't stop waiting too early /
> > > too late. Another one that I think might deserve more testing is waits on the
> > > standby while crossing timeline boundaries.
> > >
> >
> > I'll prepare a new patch for more test harnessing.
> >
> > >
> > > > From 0e5b4d1b9311a628a70218d89abf12308c9d782f Mon Sep 17 00:00:00 2001
> > > > From: Alexander Korotkov <akorotkov@postgresql.org>
> > > > Date: Thu, 9 Apr 2026 16:49:04 +0300
> > > > Subject: [PATCH v3 1/5] Add a memory barrier to GetWalRcvWriteRecPtr()
> > > >
> > > > Add pg_memory_barrier() before reading writtenUpto so that callers see
> > > > up-to-date shared memory state. This matches the barrier semantics that
> > > > GetWalRcvFlushRecPtr() and other LSN-position functions get implicitly from
> > > > their spinlock acquire/release, and in turn protects from bugs caused by
> > > > expectations of similar barrier guarantees from different LSN-position functions.
> > > >
> > > > Reported-by: Andres Freund <andres@anarazel.de>
> > > > Discussion: https://postgr.es/m/zqbppucpmkeqecfy4s5kscnru4tbk6khp3ozqz6ad2zijz354k%40w4bdf4z3wqoz
> > > > ---
> > > > src/backend/replication/walreceiverfuncs.c | 12 ++++++++++--
> > > > 1 file changed, 10 insertions(+), 2 deletions(-)
> > > >
> > > > diff --git a/src/backend/replication/walreceiverfuncs.c b/src/backend/replication/walreceiverfuncs.c
> > > > index bd5d47be964..0408ddff43e 100644
> > > > --- a/src/backend/replication/walreceiverfuncs.c
> > > > +++ b/src/backend/replication/walreceiverfuncs.c
> > > > @@ -363,14 +363,22 @@ GetWalRcvFlushRecPtr(XLogRecPtr *latestChunkStart, TimeLineID *receiveTLI)
> > > >
> > > > /*
> > > > * Returns the last+1 byte position that walreceiver has written.
> > > > - * This returns a recently written value without taking a lock.
> > > > + *
> > > > + * Use a memory barrier to ensure that callers see up-to-date shared memory
> > > > + * state, matching the barrier semantics provided by the spinlock in
> > > > + * GetWalRcvFlushRecPtr() and other LSN-position functions.
> > > > */
> > > > XLogRecPtr
> > > > GetWalRcvWriteRecPtr(void)
> > > > {
> > > > WalRcvData *walrcv = WalRcv;
> > > > + XLogRecPtr recptr;
> > > > +
> > > > + pg_memory_barrier();
> > > >
> > > > - return pg_atomic_read_u64(&walrcv->writtenUpto);
> > > > + recptr = pg_atomic_read_u64(&walrcv->writtenUpto);
> > > > +
> > > > + return recptr;
> > > > }
> > > >
> > > > /*
> > > > --
> > > > 2.39.5 (Apple Git-154)
> > > >
> > >
> > > > Subject: [PATCH v3 2/5] Fix memory ordering in WAIT FOR LSN wakeup mechanism
> > >
> > > > + /*
> > > > + * Ensure the waker's prior position store (writtenUpto, flushedUpto,
> > > > + * lastReplayedEndRecPtr, etc.) is globally visible before we read
> > > > + * minWaitedLSN. Without this barrier, the CPU could load minWaitedLSN
> > > > + * before draining the position store, leaving the position invisible to a
> > > > + * concurrently-registering waiter.
> > > > + *
> > > > + * This is the waker side of a Dekker-style handshake; pairs with
> > > > + * pg_memory_barrier() in GetCurrentLSNForWaitType() on the waiter side.
> > > > + */
> > > > + pg_memory_barrier();
> > > > +
> > > > /*
> > > > * Fast path check. Skip if currentLSN is InvalidXLogRecPtr, which means
> > > > * "wake all waiters" (e.g., during promotion when recovery ends).
> > >
> > > I'd also make this a pg_atomic_read_membarrier_u64() and the write a
> > > pg_atomic_write_membarrier_u64(). It's a lot easier to reason about this
> > > stuff if you make sure that the individual reads / write pair and have
> > > ordering implied.
> > >
> >
> > It does look more selft-contained to me.
> >
> > Here is the updated patch set based on Alexander’s earlier version.
>
> The last para of commit message in patch 2 is inaccurate after the
> getter-side barrier changes, "could read a stale position and wrongly
> timeout" is no longer the primary rationale.
The updated patchset is attached. It includes improved coverage as
suggested by Andres upthread. And documentation that WAIT FOR LSN is
timeline-blind (per off-list discussion with Xuneng).
------
Regards,
Alexander Korotkov
Supabase
Commits
GET /api/v1/messages/:b64id/commits
the thread's linked commits as JSON, with link sources.
API reference →
-
Clean up 019_replslot_limit.pl comments
- 0b866bb90368 19 (unreleased) landed
-
Stabilize 019_replslot_limit.pl: wait on slot restart_lsn
- cdb1d1cf1de6 19 (unreleased) landed
-
Fix memory ordering in WAIT FOR LSN wakeup mechanism
- a80a593ab636 19 (unreleased) landed
-
Improve WAIT FOR LSN test coverage
- cb096e6d6981 19 (unreleased) landed
-
Remove redundant WAIT FOR LSN caller-side pre-checks
- df9f938ca2ec 19 (unreleased) landed
-
Use barrier semantics when reading/writing writtenUpto
- dfb690dd5237 19 (unreleased) landed
-
Use replay position as floor for WAIT FOR LSN standby_(write|flush)
- cba67b5b87f9 19 (unreleased) landed
-
Wake standby_write/standby_flush waiters from the WAL replay loop
- e7cd592174d9 19 (unreleased) landed
-
Minimal fix for WAIT FOR ... MODE 'standby_flush'
- 29e7dbf5e4da 19 (unreleased) landed
-
Avoid syscache lookup while building a WAIT FOR tuple descriptor
- 834038c1f8d5 19 (unreleased) landed
-
Document that WAIT FOR may be interrupted by recovery conflicts
- 10484c2cc75b 19 (unreleased) landed
-
Use WAIT FOR LSN in PostgreSQL::Test::Cluster::wait_for_catchup()
- 7e8aeb9e483d 19 (unreleased) landed
- f30848cb05d4 19 (unreleased) landed
-
Wake LSN waiters before recovery target stop
- 20a8f783e15c 19 (unreleased) landed
-
Remove redundant pg_unreachable() after elog(ERROR) from ExecWaitStmt()
- 30776ca46865 19 (unreleased) landed
-
Revert "Use WAIT FOR LSN in PostgreSQL::Test::Cluster::wait_for_catchup()"
- e54ce0b2da62 19 (unreleased) landed
-
Fix variable usage in wakeupWaiters()
- bf308639bfcf 19 (unreleased) landed
-
Add tab completion for the WAIT FOR LSN MODE option
- 76948337f724 19 (unreleased) landed
-
Add the MODE option to the WAIT FOR LSN command
- 49a181b5d634 19 (unreleased) landed
-
Extend xlogwait infrastructure with write and flush wait types
- 7a39f43d885b 19 (unreleased) landed
-
Unify error messages
- 502e256f2262 19 (unreleased) cited
-
Optimize shared memory usage for WaitLSNProcInfo
- 75e82b2f5a6f 19 (unreleased) landed
-
Fix WaitLSNWakeup() fast-path check for InvalidXLogRecPtr
- ede6acef4967 19 (unreleased) landed
-
Fix incorrect function name in comments
- 23792d738158 19 (unreleased) landed
-
Add infrastructure for efficient LSN waiting
- 3b4e53a075ea 19 (unreleased) landed
-
Add pairingheap_initialize() for shared memory usage
- 8af3ae0d4b36 19 (unreleased) landed
-
Implement WAIT FOR command
- 447aae13b030 19 (unreleased) landed