Re: LISTEN denial of service with aborted transaction
От | Matt Newell |
---|---|
Тема | Re: LISTEN denial of service with aborted transaction |
Дата | |
Msg-id | 3873524.8xdXel8qyP@obsidian обсуждение исходный текст |
Ответ на | Re: LISTEN denial of service with aborted transaction (Matt Newell <newellm@blur.com>) |
Ответы |
Re: LISTEN denial of service with aborted transaction
|
Список | 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
Вложения
В списке pgsql-hackers по дате отправления: