Re: Reject WAIT FOR earlier in transaction-snapshot mode

From: Alexander Korotkov <aekorotkov(at)gmail(dot)com>
To: Sami Imseih <samimseih(dot)pg(at)gmail(dot)com>
Cc: Xuneng Zhou <xunengzhou(at)gmail(dot)com>, Álvaro Herrera <alvherre(at)kurilemu(dot)de>, Postgres hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Reject WAIT FOR earlier in transaction-snapshot mode
Date: 2026-09-17 20:52:09
Message-ID: CAPpHfdstCVxb-iXsqjZ2umJQdzFud4fypZRCVEZnEOTLyp0gGw@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

On Thu, Sep 17, 2026 at 5:53 PM Sami Imseih <samimseih(dot)pg(at)gmail(dot)com> wrote:
>
> > > Done in v6.
> >
> > Xuneng, Sami, do you think v6 is good enough?
>
> I think the user-facing documentation can be simplified considerably while
> preserving the important information. I prefer the below changes on top
> of v6:
>
> 1/ State directly that WAIT cannot be executed while the current transaction
> holds a snapshot.
> 2/ Clarify that WAIT itself does not acquire a snapshot.
> 3/ Explain that it can therefore be executed before the first snapshot-taking
> statement in a REPEATABLE READ or SERIALIZABLE transaction.
> 4/ Briefly explain why holding a snapshot can prevent a standby wait from
> completing.
>
>
> ```
> <command>DO</command> block. It also cannot be executed while the
> - current transaction holds a snapshot. A transaction running at an
> - isolation level higher than <literal>READ COMMITTED</literal> holds one
> - from its first query until it ends, so <command>WAIT</command> is
> - accepted before that query and rejected after it. An open cursor or an
> - exported snapshot has the same effect at any isolation level.
> - </para>
> -
> - <para>
> - The restriction above exists because such a snapshot could stand in
> - the way of the very replay being waited for: replaying a record that
> - removes rows the snapshot can still see raises a recovery conflict.
> - This conflict could be resolved by delaying the replay or by cancelling
> - this session. Having to run without a snapshot is also the reason why
> - <command>WAIT</command> is a command rather than a function or a procedure,
> - which execute with one held.
> - </para>
> -
> - <para>
> - The other standby modes are not independent of replay either, even though
> - they do not wait for it directly. Their positions advance as WAL arrives,
> - but WAL is recycled only at restartpoints, and a restartpoint cannot be
> - created past a checkpoint record that replay has not reached. While
> - replay is held back, <filename>pg_wal</filename> therefore keeps growing
> - past <xref linkend="guc-max-wal-size"/>, and reception stops once the file
> - system fills.
> + current transaction holds a snapshot.
> + <command>WAIT</command> itself does not acquire a snapshot, so it can be
> + executed before the first snapshot-taking statement in a
> + <literal>REPEATABLE READ</literal> or <literal>SERIALIZABLE</literal>
> + transaction. Holding a snapshot while using a standby wait mode could
> + delay WAL replay and prevent the wait from completing.
> </para>
> ```

Agreed. v7 attached: three paragraphs collapsed into one, close to your
wording. I kept three bits from v6:

* mention the cursor and the exported snapshot as those who may hold snapshots;
* "which standby_replay waits for and the other standby modes
ultimately depend on", so that write and flush are not read as exempt;
* "that is also why WAIT is a command rather than a function or a
procedure", which makes the restriction in the first sentence follow
from the same rule instead of looking arbitrary.

------
Regards,
Alexander Korotkov
Supabase

Attachment Content-Type Size
v7-0001-Say-what-WAIT-s-snapshot-restriction-actually-is.patch application/octet-stream 6.4 KB

In response to

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message David Rowley 2026-09-17 20:55:38 Re: RANGE partition pruning can still exclude the default partition
Previous Message Álvaro Rodríguez 2026-09-17 20:25:35 Re: Unexpected reindex when altering column types for partitioned tables