Re: LISTEN/NOTIFY bug: VACUUM sets frozenxid past a xid in async queue

From: Heikki Linnakangas <hlinnaka(at)iki(dot)fi>
To: Arseniy Mukhin <arseniy(dot)mukhin(dot)dev(at)gmail(dot)com>
Cc: Álvaro Herrera <alvherre(at)kurilemu(dot)de>, Joel Jacobson <joel(at)compiler(dot)org>, Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>, pgsql-hackers <pgsql-hackers(at)postgresql(dot)org>
Subject: Re: LISTEN/NOTIFY bug: VACUUM sets frozenxid past a xid in async queue
Date: 2025-11-07 08:10:25
Message-ID: bad6b199-c988-48ef-9976-b0539df098f4@iki.fi
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

On 06/11/2025 17:13, Arseniy Mukhin wrote:
> Let's say we have the queue:
>
> (tail ... pos1 ... bad_entry_pos ... head)
>
> bad_entry_pos - position of the entry where TransactionIdDidCommit fails.
>
> We have the listener L1 with pos = pos1. It means every new listener
> should process the queue from pos1 (as it's max(listener's pos)) up to
> the queue head and when they try to do it, they will fail on
> 'bad_entry'.

Gotcha.

>> Another small change we could make is to check for listenChannels == NIL
>> before calling TransactionIdDidCommit.
>
> There is a comment that describes why we need this initial reading in
> Exec_ListenPreCommit:
>
> /*
> * This is our first LISTEN, so establish our pointer.
> *
> * We set our pointer to the global tail pointer and then move it forward
> * over already-committed notifications. This ensures we cannot miss any
> * not-yet-committed notifications. We might get a few more but that
> * doesn't hurt.
>
> It seems that with such a check we will skip not-yet-committed
> notifications and always get to the HEAD. If we decide that it's ok,
> maybe we can just set 'pos' of every new listener to the HEAD without
> reading?

Right, I didn't mean skipping asyncQueueReadAllNotifications()
altogether. Just the TransactionIdDidCommit() calls in it, when
listenChannels == NIL, see attached patch. The idea is that when
'listenChannels == NIL', we're not going send the notification to the
frontend regardless of what TransactionIdDidCommit says. If we don't
call TransactionIdDidCommit, we won't fail on bad entries.

I'm not sure how much this matters. We really shouldn't have bad entries
in the queue to begin with. And if we do, a broken entry could cause all
kinds of trouble. For example, if the broken entry's (bogus) XID is
higher than current XID, XidInMVCCSnapshot() will return true and we'll
get stuck on that.

- Heikki

Attachment Content-Type Size
skip-TransactionIdDidCommit-on-first-listen.patch.txt text/plain 980 bytes

In response to

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message Peter Eisentraut 2025-11-07 08:44:22 Re: Reorganize GUC structs
Previous Message Frédéric Yhuel 2025-11-07 08:06:46 Re: [BUG] temporary file usage report with extended protocol and unnamed portals