Re: [HACKERS] make async slave to wait for lsn to be replayed

Started by Kartyshov Ivanabout 3 years ago116 messages
Jump to latest
#1Kartyshov Ivan
i.kartyshov@postgrespro.ru

Intro==========
The main purpose of the feature is to achieve
read-your-writes-consistency, while using async replica for reads and
primary for writes. In that case lsn of last modification is stored
inside
application. We cannot store this lsn inside database, since reads are
distributed across all replicas and primary.

/messages/by-id/195e2d07ead315b1620f1a053313f490@postgrespro.ru

Suggestions
==========
Lots of proposals were made how this feature may look like.
I aggregate them into the following four types.

1) Classic (wait_classic_v1.patch)
/messages/by-id/3cc883048264c2e9af022033925ff8db@postgrespro.ru
==========
advantages: multiple events, standalone WAIT
disadvantages: new words in grammar

WAIT FOR  [ANY | ALL] event [, ...]
BEGIN [ WORK | TRANSACTION ] [ transaction_mode [, ...] ]
    [ WAIT FOR [ANY | ALL] event [, ...]]
where event is one of:
LSN value
TIMEOUT number_of_milliseconds
timestamp

2) After style: Kyotaro and Freund (wait_after_within_v1.patch)
/messages/by-id/d3ff2e363af60b345f82396992595a03@postgrespro.ru
==========
advantages: no new words in grammar, standalone AFTER
disadvantages: a little harder to understand

AFTER lsn_event [ WITHIN delay_milliseconds ] [, ...]
BEGIN [ WORK | TRANSACTION ] [ transaction_mode [, ...] ]
    [ AFTER lsn_event [ WITHIN delay_milliseconds ]]
START [ WORK | TRANSACTION ] [ transaction_mode [, ...] ]
    [ AFTER lsn_event [ WITHIN delay_milliseconds ]]

3) Procedure style: Tom Lane and Kyotaro (wait_proc_v1.patch)
/messages/by-id/27171.1586439221@sss.pgh.pa.us
/messages/by-id/20210121.173009.235021120161403875.horikyota.ntt@gmail.com
==========
advantages: no new words in grammar,like it made in
pg_last_wal_replay_lsn, no snapshots need
disadvantages: a little harder to remember names
SELECT pg_waitlsn(‘LSN’, timeout);
SELECT pg_waitlsn_infinite(‘LSN’);
SELECT pg_waitlsn_no_wait(‘LSN’);

4) Brackets style: Kondratov
/messages/by-id/a8bff0350a27e0a87a6eaf0905d6737f@postgrespro.ru%C2%A0
==========
advantages: only one new word in grammar,like it made in VACUUM and
REINDEX, ability to extend parameters without grammar fixes
disadvantages: 
WAIT (LSN '16/B374D848', TIMEOUT 100);
BEGIN WAIT (LSN '16/B374D848' [, etc_options]);
...
COMMIT;

Consequence
==========
Below I provide the implementation of patches for the first three types.
I propose to discuss this feature again/

Regards

--
Ivan Kartyshov
Postgres Professional: http://www.postgrespro.com
The Russian Postgres Company

Attachments:

wait_after_within_v1.patchtext/x-diff; name=wait_after_within_v1.patchDownload+648-7
wait_classic_v1.patchtext/x-diff; name=wait_classic_v1.patchDownload+1066-11
wait_proc_v1.patchtext/x-diff; name=wait_proc_v1.patchDownload+433-3
#2Bruce Momjian
bruce@momjian.us
In reply to: Kartyshov Ivan (#1)

On Tue, 28 Feb 2023 at 05:13, Kartyshov Ivan <i.kartyshov@postgrespro.ru> wrote:

Below I provide the implementation of patches for the first three types.
I propose to discuss this feature again/

Oof, that doesn't really work with the cfbot. It tries to apply all
three patches and of course the second and third fail to apply.

In any case this seems like a lot of effort to me. I would suggest you
just pick one avenue and provide that patch for discussion and just
ask whether people would prefer any of the alternative syntaxes.

Fwiw I prefer the functions approach. I do like me some nice syntax
but I don't see any particular advantage of the special syntax in this
case. They don't seem to provide any additional expressiveness.

That said, I'm not a fan of the specific function names. Remember that
we have polymorphic functions so you could probably just have an
option argument:

pg_lsn_wait('LSN', [timeout]) returns boolean

(just call it with a timeout of 0 to do a no-wait)

I'll set the patch to "Waiting on Author" for now. If you feel you're
still looking for more opinions from others maybe set it back to Needs
Review but honestly there are a lot of patches so you probably won't
see much this commitfest unless you have a patch that shows in
cfbot.cputube.org as applying and which looks ready to commit.

--
greg

#3Michael Paquier
michael@paquier.xyz
In reply to: Bruce Momjian (#2)

On Wed, Mar 01, 2023 at 03:31:06PM -0500, Greg Stark wrote:

Fwiw I prefer the functions approach. I do like me some nice syntax
but I don't see any particular advantage of the special syntax in this
case. They don't seem to provide any additional expressiveness.

So do I, eventhough I saw a point that sticking to a function or a
procedure approach makes the wait stick with more MVCC rules, like the
fact that the wait may be holding a snapshot for longer than
necessary. The grammar can be more extensible without more keywords
with DefElems, still I'd like to think that we should not introduce
more restrictions in the parser if we have ways to work around it.
Using a procedure or function approach is more extensible in its own
ways, and it also depends on the data waiting for (there could be more
than one field as well for a single wait pattern?).

I'll set the patch to "Waiting on Author" for now. If you feel you're
still looking for more opinions from others maybe set it back to Needs
Review but honestly there are a lot of patches so you probably won't
see much this commitfest unless you have a patch that shows in
cfbot.cputube.org as applying and which looks ready to commit.

While looking at all the patches proposed, I have noticed that all the
approaches proposed force a wakeup of the waiters in the redo loop of
the startup process for each record, before reading the next record.
It strikes me that there is some interaction with custom resource
managers here, where it is possible to poke at the waiters not for
each record, but after reading some specific records. Something
out-of-core would not be as responsive as the per-record approach,
still responsive enough that the waiters wait on input for an
acceptable amount of time, depending on the frequency of the records
generated by a primary to wake them up. Just something that popped
into my mind while looking a bit at the threads.
--
Michael

#4Peter Eisentraut
peter_e@gmx.net
In reply to: Kartyshov Ivan (#1)

On 28.02.23 11:10, Kartyshov Ivan wrote:

3) Procedure style: Tom Lane and Kyotaro (wait_proc_v1.patch)
/messages/by-id/27171.1586439221@sss.pgh.pa.us
/messages/by-id/20210121.173009.235021120161403875.horikyota.ntt@gmail.com
==========
advantages: no new words in grammar,like it made in
pg_last_wal_replay_lsn, no snapshots need
disadvantages: a little harder to remember names
SELECT pg_waitlsn(‘LSN’, timeout);
SELECT pg_waitlsn_infinite(‘LSN’);
SELECT pg_waitlsn_no_wait(‘LSN’);

Of the presented options, I prefer this one. (Maybe with a "_" between
"wait" and "lsn".)

But I wonder how a client is going to get the LSN. How would all of
this be used by a client? I can think of a scenarios where you have an
application that issues a bunch of SQL commands and you have some kind
of pooler in the middle that redirects those commands to different
hosts, and what you really want is to have it transparently behave as if
it's just a single host. Do we want to inject a bunch of "SELECT
pg_get_lsn()", "SELECT pg_wait_lsn()" calls into that?

I'm tempted to think this could be a protocol-layer facility. Every
query automatically returns the current LSN, and every query can also
send along an LSN to wait for, and the client library would just keep
track of the LSN for (what it thinks of as) the connection. So you get
some automatic serialization without having to modify your client code.

That said, exposing this functionality using functions could be a valid
step in that direction, so that you can at least build out the actual
internals of the functionality and test it out.

#5Kartyshov Ivan
i.kartyshov@postgrespro.ru
In reply to: Peter Eisentraut (#4)

Here I made new patch of feature, discussed above.

WAIT FOR procedure - waits for certain lsn on pause
==========
Synopsis
==========
SELECT pg_wait_lsn(‘LSN’, timeout) returns boolean

Where timeout = 0, will wait infinite without timeout
And if timeout = 1, then just check if lsn was replayed

How to use it
==========

Greg Stark wrote:

That said, I'm not a fan of the specific function names. Remember that
we have polymorphic functions so you could probably just have an
option argument:

If you have any example, I will be glade to see them. Ьy searches have
not been fruitful.

Michael Paquier wrote:

While looking at all the patches proposed, I have noticed that all the
approaches proposed force a wakeup of the waiters in the redo loop of
the startup process for each record, before reading the next record.
It strikes me that there is some interaction with custom resource
managers here, where it is possible to poke at the waiters not for
each record, but after reading some specific records. Something
out-of-core would not be as responsive as the per-record approach,
still responsive enough that the waiters wait on input for an
acceptable amount of time, depending on the frequency of the records
generated by a primary to wake them up. Just something that popped
into my mind while looking a bit at the threads.

I`ll work on this idea to have less impact on the redo system.

On 2023-03-02 13:33, Peter Eisentraut wrote:

But I wonder how a client is going to get the LSN. How would all of
this be used by a client?

As I wrote earlier main purpose of the feature is to achieve
read-your-writes-consistency, while using async replica for reads and
primary for writes. In that case lsn of last modification is stored
inside application.

I'm tempted to think this could be a protocol-layer facility. Every
query automatically returns the current LSN, and every query can also
send along an LSN to wait for, and the client library would just keep
track of the LSN for (what it thinks of as) the connection. So you
get some automatic serialization without having to modify your client
code.

Yes it sounds very tempted. But I think community will be against it.

--
Ivan Kartyshov
Postgres Professional: http://www.postgrespro.com
The Russian Postgres Company

Attachments:

wait_proc_v2.patchtext/x-diff; name=wait_proc_v2.patchDownload+408-3
#6Kartyshov Ivan
i.kartyshov@postgrespro.ru
In reply to: Peter Eisentraut (#4)

Update patch to fix conflict with master
--
Ivan Kartyshov
Postgres Professional: http://www.postgrespro.com
The Russian Postgres Company

Attachments:

wait_proc_v3.patchtext/x-diff; name=wait_proc_v3.patchDownload+408-3
#7Kartyshov Ivan
i.kartyshov@postgrespro.ru
In reply to: Peter Eisentraut (#4)

Fix build.meson troubles

--
Ivan Kartyshov
Postgres Professional: http://www.postgrespro.com
The Russian Postgres Company

Attachments:

wait_proc_v4.patchtext/x-diff; name=wait_proc_v4.patchDownload+409-3
#8Kartyshov Ivan
i.kartyshov@postgrespro.ru
In reply to: Kartyshov Ivan (#7)

All rebased and tested

--
Ivan Kartyshov
Postgres Professional: http://www.postgrespro.com
The Russian Postgres Company@postgrespro.ru>
 

Attachments:

wait_proc_v5.patchtext/x-patchDownload+409-3
#9Alexander Korotkov
aekorotkov@gmail.com
In reply to: Kartyshov Ivan (#8)

Hi, Ivan!

On Fri, Jun 30, 2023 at 11:32 AM Картышов Иван <i.kartyshov@postgrespro.ru>
wrote:

All rebased and tested

Thank you for continuing to work on this patch.

I see you're concentrating on the procedural version of this feature. But
when you're calling a procedure within a normal SQL statement, the executor
gets a snapshot and holds it until the procedure finishes. In the case the
WAL record conflicts with this snapshot, the query will be canceled.
Alternatively, when hot_standby_feedback = on, the query and WAL replayer
will be in a deadlock (WAL replayer will wait for the query to finish, and
the query will wait for WAL replayed). Do you see this issue? Or do you
think I'm missing something?

XLogRecPtr
GetMinWaitedLSN(void)
{
return state->min_lsn.value;
}

You definitely shouldn't access directly the fields
inside pg_atomic_uint64. In this particular case, you should
use pg_atomic_read_u64().

Also, I think there is a race condition.

/* Check if we already reached the needed LSN */
if (cur_lsn >= target_lsn)
return true;

AddWaitedLSN(target_lsn);

Imagine, PerformWalRecovery() will replay a record after the check, but
before AddWaitedLSN(). This code will start the waiting cycle even if the
LSN is already achieved. Surely this cycle will end soon because it
rechecks LSN value each 100 ms. But anyway, I think there should be
another check after AddWaitedLSN() for the sake of consistency.

------
Regards,
Alexander Korotkov

#10Alexander Korotkov
aekorotkov@gmail.com
In reply to: Alexander Korotkov (#9)

Hi!

On Wed, Oct 4, 2023 at 1:22 PM Alexander Korotkov <aekorotkov@gmail.com> wrote:

I see you're concentrating on the procedural version of this feature. But when you're calling a procedure within a normal SQL statement, the executor gets a snapshot and holds it until the procedure finishes. In the case the WAL record conflicts with this snapshot, the query will be canceled. Alternatively, when hot_standby_feedback = on, the query and WAL replayer will be in a deadlock (WAL replayer will wait for the query to finish, and the query will wait for WAL replayed). Do you see this issue? Or do you think I'm missing something?

I'm sorry, I actually meant hot_standby_feedback = off
(hot_standby_feedback = on actually avoids query conflicts). I
managed to reproduce this problem.

master: create table test as (select i from generate_series(1,10000) i);
slave conn1: select pg_wal_replay_pause();
master: delete from test;
master: vacuum test;
master: select pg_current_wal_lsn();
slave conn2: select pg_wait_lsn('the value from previous query'::pg_lsn, 0);
slave conn1: select pg_wal_replay_resume();
slave conn2: ERROR: canceling statement due to conflict with recovery
DETAIL: User query might have needed to see row versions that must be removed.

Needless to say, this is very undesirable behavior. This happens
because pg_wait_lsn() has to run within a snapshot as any other
function. This is why I think this functionality should be
implemented as a separate statement.

Another issue I found is that pg_wait_lsn() hangs on the primary. I
think an error should be reported instead.

------
Regards,
Alexander Korotkov

#11Kartyshov Ivan
i.kartyshov@postgrespro.ru
In reply to: Alexander Korotkov (#10)

Alexander, thank you for your review and pointing this issues. According to
them I made some fixes and rebase all patch.

But I can`t repeat your ERROR. Not with hot_standby_feedback = on nor 
hot_standby_feedback = off.master: create table test as (select i from generate_series(1,10000) i);
slave conn1: select pg_wal_replay_pause();
master: delete from test;
master: vacuum test;
master: select pg_current_wal_lsn();
slave conn2: select pg_wait_lsn('the value from previous query'::pg_lsn, 0);
slave conn1: select pg_wal_replay_resume();
slave conn2: ERROR: canceling statement due to conflict with recovery
DETAIL: User query might have needed to see row versions that must be removed.Also I use little hack to work out of snapshot similar to SnapshotResetXmin.

Patch rebased and ready for review.

 

Attachments:

wait_proc_v6.patchtext/x-patchDownload+418-3
#12Bowen Shi
zxwsbg12138@gmail.com
In reply to: Kartyshov Ivan (#11)

Hi,

I used the latest code and found some conflicts while applying. Which PG
version did you rebase?

Regards
Bowen Shi

#13Alexander Korotkov
aekorotkov@gmail.com
In reply to: Bowen Shi (#12)

On Thu, Nov 23, 2023 at 5:52 AM Bowen Shi <zxwsbg12138@gmail.com> wrote:

I used the latest code and found some conflicts while applying. Which PG version did you rebase?

I've successfully applied the patch on bc3c8db8ae. But I've used
"patch -p1 < wait_proc_v6.patch", git am doesn't work.

------
Regards,
Alexander Korotkov

#14Alexander Korotkov
aekorotkov@gmail.com
In reply to: Kartyshov Ivan (#11)

On Mon, Nov 20, 2023 at 1:10 PM Картышов Иван
<i.kartyshov@postgrespro.ru> wrote:

Alexander, thank you for your review and pointing this issues. According to
them I made some fixes and rebase all patch.

But I can`t repeat your ERROR. Not with hot_standby_feedback = on nor
hot_standby_feedback = off.

master: create table test as (select i from generate_series(1,10000) i);
slave conn1: select pg_wal_replay_pause();
master: delete from test;
master: vacuum test;
master: select pg_current_wal_lsn();
slave conn2: select pg_wait_lsn('the value from previous query'::pg_lsn, 0);
slave conn1: select pg_wal_replay_resume();
slave conn2: ERROR: canceling statement due to conflict with recovery
DETAIL: User query might have needed to see row versions that must be removed.

Also I use little hack to work out of snapshot similar to SnapshotResetXmin.

Patch rebased and ready for review.

I've retried my case with v6 and it doesn't fail anymore. But I
wonder how safe it is to reset xmin within the user-visible function?
We have no guarantee that the function is not called inside the
complex query. Then how will the rest of the query work with xmin
reset? Separate utility statement still looks like more safe option
for me.

------
Regards,
Alexander Korotkov

#15Kartyshov Ivan
i.kartyshov@postgrespro.ru
In reply to: Alexander Korotkov (#14)

On 2023-11-27 03:08, Alexander Korotkov wrote:

I've retried my case with v6 and it doesn't fail anymore. But I
wonder how safe it is to reset xmin within the user-visible function?
We have no guarantee that the function is not called inside the
complex query. Then how will the rest of the query work with xmin
reset? Separate utility statement still looks like more safe option
for me.

As you mentioned, we can`t guarantee that the function is not called
inside the complex query, but we can return the xmin after waiting.
But you are right and separate utility statement still looks more safe.
So I want to bring up the discussion on separate utility statement
again.

--
Ivan Kartyshov
Postgres Professional: www.postgrespro.com

#16Kartyshov Ivan
i.kartyshov@postgrespro.ru
In reply to: Alexander Korotkov (#14)

Should rise disscusion on separate utility statement or find
case where procedure version is failed.

1) Classic (wait_classic_v3.patch)
/messages/by-id/3cc883048264c2e9af022033925ff8db@postgrespro.ru
==========
advantages: multiple wait events, separate WAIT FOR statement
disadvantages: new words in grammar

WAIT FOR [ANY | ALL] event [, ...]
BEGIN [ WORK | TRANSACTION ] [ transaction_mode [, ...] ]
[ WAIT FOR [ANY | ALL] event [, ...]]
event:
LSN value
TIMEOUT number_of_milliseconds
timestamp

2) After style: Kyotaro and Freund (wait_after_within_v2.patch)
/messages/by-id/d3ff2e363af60b345f82396992595a03@postgrespro.ru
==========
advantages: no new words in grammar
disadvantages: a little harder to understand

AFTER lsn_event [ WITHIN delay_milliseconds ] [, ...]
BEGIN [ WORK | TRANSACTION ] [ transaction_mode [, ...] ]
[ AFTER lsn_event [ WITHIN delay_milliseconds ]]
START [ WORK | TRANSACTION ] [ transaction_mode [, ...] ]
[ AFTER lsn_event [ WITHIN delay_milliseconds ]]

3) Procedure style: Tom Lane and Kyotaro (wait_proc_v7.patch)
/messages/by-id/27171.1586439221@sss.pgh.pa.us
/messages/by-id/20210121.173009.235021120161403875.horikyota.ntt@gmail.com
==========
advantages: no new words in grammar,like it made in
pg_last_wal_replay_lsn
disadvantages: use snapshot xmin trick
SELECT pg_waitlsn(‘LSN’, timeout);
SELECT pg_waitlsn_infinite(‘LSN’);
SELECT pg_waitlsn_no_wait(‘LSN’);

Regards
--
Ivan Kartyshov
Postgres Professional: www.postgrespro.com

Attachments:

wait_after_within_v2.patchtext/x-diff; name=wait_after_within_v2.patchDownload+658-7
wait_classic_v3.patchtext/x-diff; name=wait_classic_v3.patchDownload+1076-11
wait_proc_v7.patchtext/x-diff; name=wait_proc_v7.patchDownload+420-3
#17Alexander Korotkov
aekorotkov@gmail.com
In reply to: Kartyshov Ivan (#15)

On Fri, Dec 8, 2023 at 11:20 AM Kartyshov Ivan
<i.kartyshov@postgrespro.ru> wrote:

On 2023-11-27 03:08, Alexander Korotkov wrote:

I've retried my case with v6 and it doesn't fail anymore. But I
wonder how safe it is to reset xmin within the user-visible function?
We have no guarantee that the function is not called inside the
complex query. Then how will the rest of the query work with xmin
reset? Separate utility statement still looks like more safe option
for me.

As you mentioned, we can`t guarantee that the function is not called
inside the complex query, but we can return the xmin after waiting.

Returning xmin back isn't safe. Especially after potentially long
waiting. The snapshot could be no longer valid, because the
corresponding tuples could be VACUUM'ed.

------
Regards,
Alexander Korotkov

#18Alexander Korotkov
aekorotkov@gmail.com
In reply to: Kartyshov Ivan (#16)

On Fri, Dec 8, 2023 at 11:46 AM Kartyshov Ivan
<i.kartyshov@postgrespro.ru> wrote:

Should rise disscusion on separate utility statement or find
case where procedure version is failed.

1) Classic (wait_classic_v3.patch)
/messages/by-id/3cc883048264c2e9af022033925ff8db@postgrespro.ru
==========
advantages: multiple wait events, separate WAIT FOR statement
disadvantages: new words in grammar

WAIT FOR [ANY | ALL] event [, ...]
BEGIN [ WORK | TRANSACTION ] [ transaction_mode [, ...] ]
[ WAIT FOR [ANY | ALL] event [, ...]]
event:
LSN value
TIMEOUT number_of_milliseconds
timestamp

Nice, but as you stated requires new keywords.

2) After style: Kyotaro and Freund (wait_after_within_v2.patch)
/messages/by-id/d3ff2e363af60b345f82396992595a03@postgrespro.ru
==========
advantages: no new words in grammar
disadvantages: a little harder to understand

AFTER lsn_event [ WITHIN delay_milliseconds ] [, ...]
BEGIN [ WORK | TRANSACTION ] [ transaction_mode [, ...] ]
[ AFTER lsn_event [ WITHIN delay_milliseconds ]]
START [ WORK | TRANSACTION ] [ transaction_mode [, ...] ]
[ AFTER lsn_event [ WITHIN delay_milliseconds ]]

+1 from me

3) Procedure style: Tom Lane and Kyotaro (wait_proc_v7.patch)
/messages/by-id/27171.1586439221@sss.pgh.pa.us
/messages/by-id/20210121.173009.235021120161403875.horikyota.ntt@gmail.com
==========
advantages: no new words in grammar,like it made in
pg_last_wal_replay_lsn
disadvantages: use snapshot xmin trick
SELECT pg_waitlsn(‘LSN’, timeout);
SELECT pg_waitlsn_infinite(‘LSN’);
SELECT pg_waitlsn_no_wait(‘LSN’);

Nice, because simplicity. But only safe if called within the simple
query containing nothing else. Validating this from the function
kills the simplicity.

------
Regards,
Alexander Korotkov

#19vignesh C
vignesh21@gmail.com
In reply to: Kartyshov Ivan (#16)

On Fri, 8 Dec 2023 at 15:17, Kartyshov Ivan <i.kartyshov@postgrespro.ru> wrote:

Should rise disscusion on separate utility statement or find
case where procedure version is failed.

1) Classic (wait_classic_v3.patch)
/messages/by-id/3cc883048264c2e9af022033925ff8db@postgrespro.ru
==========
advantages: multiple wait events, separate WAIT FOR statement
disadvantages: new words in grammar

WAIT FOR [ANY | ALL] event [, ...]
BEGIN [ WORK | TRANSACTION ] [ transaction_mode [, ...] ]
[ WAIT FOR [ANY | ALL] event [, ...]]
event:
LSN value
TIMEOUT number_of_milliseconds
timestamp

2) After style: Kyotaro and Freund (wait_after_within_v2.patch)
/messages/by-id/d3ff2e363af60b345f82396992595a03@postgrespro.ru
==========
advantages: no new words in grammar
disadvantages: a little harder to understand

AFTER lsn_event [ WITHIN delay_milliseconds ] [, ...]
BEGIN [ WORK | TRANSACTION ] [ transaction_mode [, ...] ]
[ AFTER lsn_event [ WITHIN delay_milliseconds ]]
START [ WORK | TRANSACTION ] [ transaction_mode [, ...] ]
[ AFTER lsn_event [ WITHIN delay_milliseconds ]]

3) Procedure style: Tom Lane and Kyotaro (wait_proc_v7.patch)
/messages/by-id/27171.1586439221@sss.pgh.pa.us
/messages/by-id/20210121.173009.235021120161403875.horikyota.ntt@gmail.com
==========
advantages: no new words in grammar,like it made in
pg_last_wal_replay_lsn
disadvantages: use snapshot xmin trick
SELECT pg_waitlsn(‘LSN’, timeout);
SELECT pg_waitlsn_infinite(‘LSN’);
SELECT pg_waitlsn_no_wait(‘LSN’);

Few of the tests have aborted at [1]https://cirrus-ci.com/task/5618308515364864 in CFBot with:
0000058`9c7ff550 00007ff6`5bdff1f4
postgres!pg_atomic_compare_exchange_u64_impl(
struct pg_atomic_uint64 * ptr = 0x00000000`00000008,
unsigned int64 * expected = 0x00000058`9c7ff5a0,
unsigned int64 newval = 0)+0x34
[c:\cirrus\src\include\port\atomics\generic-msvc.h @ 83]
00000058`9c7ff580 00007ff6`5bdff256 postgres!pg_atomic_read_u64_impl(
struct pg_atomic_uint64 * ptr = 0x00000000`00000008)+0x24
[c:\cirrus\src\include\port\atomics\generic.h @ 323]
00000058`9c7ff5c0 00007ff6`5bdfef67 postgres!pg_atomic_read_u64(
struct pg_atomic_uint64 * ptr = 0x00000000`00000008)+0x46
[c:\cirrus\src\include\port\atomics.h @ 430]
00000058`9c7ff5f0 00007ff6`5bc98fc3
postgres!GetMinWaitedLSN(void)+0x17
[c:\cirrus\src\backend\commands\wait.c @ 176]
00000058`9c7ff620 00007ff6`5bc82fb9
postgres!PerformWalRecovery(void)+0x4c3
[c:\cirrus\src\backend\access\transam\xlogrecovery.c @ 1788]
00000058`9c7ff6e0 00007ff6`5bffc651
postgres!StartupXLOG(void)+0x989
[c:\cirrus\src\backend\access\transam\xlog.c @ 5562]
00000058`9c7ff870 00007ff6`5bfed38b
postgres!StartupProcessMain(void)+0xd1
[c:\cirrus\src\backend\postmaster\startup.c @ 288]
00000058`9c7ff8a0 00007ff6`5bff49fd postgres!AuxiliaryProcessMain(
AuxProcType auxtype = StartupProcess (0n0))+0x1fb
[c:\cirrus\src\backend\postmaster\auxprocess.c @ 139]
00000058`9c7ff8e0 00007ff6`5beb7674 postgres!SubPostmasterMain(

More details are available at [2]https://api.cirrus-ci.com/v1/artifact/task/5618308515364864/crashlog/crashlog-postgres.exe_0008_2023-12-08_07-48-37-722.txt.

[1]: https://cirrus-ci.com/task/5618308515364864
[2]: https://api.cirrus-ci.com/v1/artifact/task/5618308515364864/crashlog/crashlog-postgres.exe_0008_2023-12-08_07-48-37-722.txt

Regards,
Vignesh

#20Kartyshov Ivan
i.kartyshov@postgrespro.ru
In reply to: vignesh C (#19)

Rebased and ready for review.
I left only versions (due to irreparable problems)

1) Classic (wait_classic_v4.patch)
/messages/by-id/3cc883048264c2e9af022033925ff8db@postgrespro.ru
==========
advantages: multiple wait events, separate WAIT FOR statement
disadvantages: new words in grammar

WAIT FOR [ANY | ALL] event [, ...]
BEGIN [ WORK | TRANSACTION ] [ transaction_mode [, ...] ]
[ WAIT FOR [ANY | ALL] event [, ...]]
event:
LSN value
TIMEOUT number_of_milliseconds
timestamp

2) After style: Kyotaro and Freund (wait_after_within_v3.patch)
/messages/by-id/d3ff2e363af60b345f82396992595a03@postgrespro.ru
==========
advantages: no new words in grammar
disadvantages: a little harder to understand

AFTER lsn_event [ WITHIN delay_milliseconds ] [, ...]
BEGIN [ WORK | TRANSACTION ] [ transaction_mode [, ...] ]
[ AFTER lsn_event [ WITHIN delay_milliseconds ]]
START [ WORK | TRANSACTION ] [ transaction_mode [, ...] ]
[ AFTER lsn_event [ WITHIN delay_milliseconds ]]

--
Ivan Kartyshov
Postgres Professional: www.postgrespro.com

Attachments:

wait_classic_v4.patchtext/x-diff; name=wait_classic_v4.patchDownload+1076-11
wait_after_within_v3.patchtext/x-diff; name=wait_after_within_v3.patchDownload+658-7
#21Kartyshov Ivan
i.kartyshov@postgrespro.ru
In reply to: Kartyshov Ivan (#20)
#22Peter Smith
smithpb2250@gmail.com
In reply to: Kartyshov Ivan (#21)
#23Dilip Kumar
dilipbalaut@gmail.com
In reply to: Kartyshov Ivan (#21)
#24Kartyshov Ivan
i.kartyshov@postgrespro.ru
In reply to: Kartyshov Ivan (#16)
#25Kartyshov Ivan
i.kartyshov@postgrespro.ru
In reply to: Kartyshov Ivan (#24)
#26Amit Kapila
amit.kapila16@gmail.com
In reply to: Kartyshov Ivan (#25)
#27Alexander Korotkov
aekorotkov@gmail.com
In reply to: Amit Kapila (#26)
#28Alexander Korotkov
aekorotkov@gmail.com
In reply to: Alexander Korotkov (#27)
#29Alexander Korotkov
aekorotkov@gmail.com
In reply to: Alexander Korotkov (#28)
#30Kartyshov Ivan
i.kartyshov@postgrespro.ru
In reply to: Alexander Korotkov (#27)
#31Kartyshov Ivan
i.kartyshov@postgrespro.ru
In reply to: Kartyshov Ivan (#30)
#32Alexander Korotkov
aekorotkov@gmail.com
In reply to: Kartyshov Ivan (#31)
#33Bharath Rupireddy
bharath.rupireddyforpostgres@gmail.com
In reply to: Alexander Korotkov (#32)
#34Amit Kapila
amit.kapila16@gmail.com
In reply to: Alexander Korotkov (#28)
#35Bharath Rupireddy
bharath.rupireddyforpostgres@gmail.com
In reply to: Amit Kapila (#34)
#36Alexander Korotkov
aekorotkov@gmail.com
In reply to: Bharath Rupireddy (#35)
#37Amit Kapila
amit.kapila16@gmail.com
In reply to: Alexander Korotkov (#36)
#38Alexander Korotkov
aekorotkov@gmail.com
In reply to: Amit Kapila (#37)
#39Amit Kapila
amit.kapila16@gmail.com
In reply to: Alexander Korotkov (#38)
#40Alexander Korotkov
aekorotkov@gmail.com
In reply to: Amit Kapila (#39)
#41Kartyshov Ivan
i.kartyshov@postgrespro.ru
In reply to: Alexander Korotkov (#40)
#42Kartyshov Ivan
i.kartyshov@postgrespro.ru
In reply to: Bharath Rupireddy (#33)
#43Alexander Korotkov
aekorotkov@gmail.com
In reply to: Kartyshov Ivan (#42)
#44Peter Eisentraut
peter_e@gmx.net
In reply to: Kartyshov Ivan (#41)
#45Peter Eisentraut
peter_e@gmx.net
In reply to: Alexander Korotkov (#36)
#46Kartyshov Ivan
i.kartyshov@postgrespro.ru
In reply to: Peter Eisentraut (#45)
#47Kartyshov Ivan
i.kartyshov@postgrespro.ru
In reply to: Kartyshov Ivan (#46)
#48Kartyshov Ivan
i.kartyshov@postgrespro.ru
In reply to: Peter Eisentraut (#45)
#49Bharath Rupireddy
bharath.rupireddyforpostgres@gmail.com
In reply to: Peter Eisentraut (#45)
#50Kartyshov Ivan
i.kartyshov@postgrespro.ru
In reply to: Bharath Rupireddy (#49)
#51Alexander Korotkov
aekorotkov@gmail.com
In reply to: Peter Eisentraut (#44)
#52Alexander Korotkov
aekorotkov@gmail.com
In reply to: Peter Eisentraut (#45)
#53Alexander Korotkov
aekorotkov@gmail.com
In reply to: Bharath Rupireddy (#49)
#54Alexander Korotkov
aekorotkov@gmail.com
In reply to: Kartyshov Ivan (#50)
#55Alexander Korotkov
aekorotkov@gmail.com
In reply to: Alexander Korotkov (#54)
#56Thomas Munro
thomas.munro@gmail.com
In reply to: Alexander Korotkov (#55)
#57Alexander Korotkov
aekorotkov@gmail.com
In reply to: Thomas Munro (#56)
#58Alexander Korotkov
aekorotkov@gmail.com
In reply to: Kartyshov Ivan (#46)
#59Euler Taveira
euler@eulerto.com
In reply to: Alexander Korotkov (#57)
#60Alexander Korotkov
aekorotkov@gmail.com
In reply to: Euler Taveira (#59)
#61Pavel Borisov
pashkin.elfe@gmail.com
In reply to: Alexander Korotkov (#60)
#62Euler Taveira
euler@eulerto.com
In reply to: Alexander Korotkov (#60)
#63Alexander Korotkov
aekorotkov@gmail.com
In reply to: Euler Taveira (#62)
#64Kartyshov Ivan
i.kartyshov@postgrespro.ru
In reply to: Alexander Korotkov (#63)
#65Alexander Korotkov
aekorotkov@gmail.com
In reply to: Kartyshov Ivan (#64)
#66Bharath Rupireddy
bharath.rupireddyforpostgres@gmail.com
In reply to: Alexander Korotkov (#65)
#67Alexander Korotkov
aekorotkov@gmail.com
In reply to: Bharath Rupireddy (#66)
#68Bharath Rupireddy
bharath.rupireddyforpostgres@gmail.com
In reply to: Alexander Korotkov (#67)
#69Alexander Korotkov
aekorotkov@gmail.com
In reply to: Bharath Rupireddy (#68)
#70Andy Fan
zhihui.fan1213@gmail.com
In reply to: Alexander Korotkov (#69)
#71Alexander Korotkov
aekorotkov@gmail.com
In reply to: Andy Fan (#70)
#72Andy Fan
zhihui.fan1213@gmail.com
In reply to: Alexander Korotkov (#71)
#73Kartyshov Ivan
i.kartyshov@postgrespro.ru
In reply to: Andy Fan (#72)
#74Bharath Rupireddy
bharath.rupireddyforpostgres@gmail.com
In reply to: Kartyshov Ivan (#73)
#75Andy Fan
zhihui.fan1213@gmail.com
In reply to: Bharath Rupireddy (#74)
#76Alexander Korotkov
aekorotkov@gmail.com
In reply to: Kartyshov Ivan (#73)
#77Alexander Korotkov
aekorotkov@gmail.com
In reply to: Andy Fan (#75)
#78Kartyshov Ivan
i.kartyshov@postgrespro.ru
In reply to: Bharath Rupireddy (#74)
#79Alvaro Herrera
alvherre@2ndquadrant.com
In reply to: Alexander Korotkov (#69)
#80Daniel Gustafsson
daniel@yesql.se
In reply to: Alvaro Herrera (#79)
#81Andy Fan
zhihui.fan1213@gmail.com
In reply to: Alexander Korotkov (#77)
#82Alexander Korotkov
aekorotkov@gmail.com
In reply to: Alvaro Herrera (#79)
#83Alvaro Herrera
alvherre@2ndquadrant.com
In reply to: Alexander Korotkov (#82)
#84Alexander Korotkov
aekorotkov@gmail.com
In reply to: Alvaro Herrera (#83)
#85Pavel Borisov
pashkin.elfe@gmail.com
In reply to: Alexander Korotkov (#84)
#86Alexander Korotkov
aekorotkov@gmail.com
In reply to: Pavel Borisov (#85)
#87Alvaro Herrera
alvherre@2ndquadrant.com
In reply to: Alexander Korotkov (#86)
#88Alexander Korotkov
aekorotkov@gmail.com
In reply to: Alvaro Herrera (#87)
#89Kartyshov Ivan
i.kartyshov@postgrespro.ru
In reply to: Alvaro Herrera (#87)
#90Heikki Linnakangas
heikki.linnakangas@enterprisedb.com
In reply to: Alexander Korotkov (#88)
#91Alexander Korotkov
aekorotkov@gmail.com
In reply to: Heikki Linnakangas (#90)
#92Heikki Linnakangas
heikki.linnakangas@enterprisedb.com
In reply to: Alexander Korotkov (#91)
#93Kartyshov Ivan
i.kartyshov@postgrespro.ru
In reply to: Alexander Korotkov (#91)
#94Alexander Korotkov
aekorotkov@gmail.com
In reply to: Kartyshov Ivan (#93)
#95Alexander Korotkov
aekorotkov@gmail.com
In reply to: Alexander Korotkov (#94)
#96Kyotaro Horiguchi
horikyota.ntt@gmail.com
In reply to: Alexander Korotkov (#95)
#97Kartyshov Ivan
i.kartyshov@postgrespro.ru
In reply to: Kyotaro Horiguchi (#96)
#98Kartyshov Ivan
i.kartyshov@postgrespro.ru
In reply to: Kartyshov Ivan (#97)
#99Alexander Korotkov
aekorotkov@gmail.com
In reply to: Kartyshov Ivan (#97)
#100Alexander Korotkov
aekorotkov@gmail.com
In reply to: Alexander Korotkov (#99)
#101Alexander Korotkov
aekorotkov@gmail.com
In reply to: Alexander Korotkov (#100)
#102Kevin Hale Boyes
kcboyes@gmail.com
In reply to: Alexander Korotkov (#101)
#103Alexander Korotkov
aekorotkov@gmail.com
In reply to: Kevin Hale Boyes (#102)
#104Alexander Korotkov
aekorotkov@gmail.com
In reply to: Alexander Korotkov (#103)
#105Michael Paquier
michael@paquier.xyz
In reply to: Alexander Korotkov (#104)
#106Alexander Korotkov
aekorotkov@gmail.com
In reply to: Michael Paquier (#105)
#107Alexander Korotkov
aekorotkov@gmail.com
In reply to: Alexander Korotkov (#106)
#108Alexander Korotkov
aekorotkov@gmail.com
In reply to: Michael Paquier (#105)
#109Alexander Korotkov
aekorotkov@gmail.com
In reply to: Alexander Korotkov (#104)
#110Alexander Korotkov
aekorotkov@gmail.com
In reply to: Alexander Korotkov (#109)
#111Alexander Korotkov
aekorotkov@gmail.com
In reply to: Alexander Korotkov (#108)
#112Alexander Lakhin
exclusion@gmail.com
In reply to: Alexander Korotkov (#110)
#113Alexander Korotkov
aekorotkov@gmail.com
In reply to: Alexander Lakhin (#112)
#114Alexander Lakhin
exclusion@gmail.com
In reply to: Alexander Korotkov (#113)
#115Alexander Korotkov
aekorotkov@gmail.com
In reply to: Alexander Lakhin (#114)
#116Alexander Lakhin
exclusion@gmail.com
In reply to: Alexander Korotkov (#115)