Re: LISTEN denial of service with aborted transaction - Mailing list pgsql-hackers

From Matt Newell
Subject Re: LISTEN denial of service with aborted transaction
Date
Msg-id 3873524.8xdXel8qyP@obsidian
Whole thread Raw
In response to Re: LISTEN denial of service with aborted transaction  (Matt Newell <newellm@blur.com>)
Responses Re: LISTEN denial of service with aborted transaction
List pgsql-hackers
>
> > After further thought, I wonder whether instead of having an incoming
> > listener initialize its "pos" to QUEUE_TAIL, we couldn't have it
> > initialize to the maximum "pos" among existing listeners (with a floor of
> > QUEUE_TAIL of course).  If any other listener has advanced over a given
> > message X, then X was committed (or aborted) earlier and the new listener
> > is not required to return it; so it should be all right to take that
> > listener's "pos" as a starting point.
>
> That's a great idea and I will try it.  It does need to be the maximum
> position of existing listeners *with matching db oid" since
> asyncQueueReadAllNotifications doesn't check transaction status if the db
> oid doesn't match it's own.  Another advantage of this approach is that a
> queued notify from an open transaction in one database won't incur
> additional cost on listens coming from other databases, whereas with my
> patch such a situation will prevent firstUncommitted from advancing.
>


Patch attached works great.  I added the dboid to the QueueBackendStatus
struct but that might not be needed if there is an easy and fast way to get a
db oid from a backend pid.

I also skip the max pos calculation loop if QUEUE_HEAD is on the same page as
QUEUE_TAIL, with the thought that it's not desirable to increase the time that
AsyncQueueLock is held if the queue is small and
asyncQueueReadAllNotifications will execute quickly.

I then noticed that we are taking the same lock twice in a row to read the
same values, first in Exec_ListenPreCommit then in
asyncQueueReadAllNotifications, and much of the time the latter will simply
return because pos will already be at QUEUE_HEAD.  I prepared a second patch
that splits asyncQueueReadAllNotifications. Exec_ListPreCommit then only calls
the worker version only when needed.  This avoids the duplicate lock.

Thanks,
Matt Newell
Attachment

pgsql-hackers by date:

Previous
From: Paul Ramsey
Date:
Subject: Re: [PATCH] postgres_fdw extension support
Next
From: Josh Berkus
Date:
Subject: Re: No Issue Tracker - Say it Ain't So!