Re: SHARED locks barging behaviour

Поиск
Список
Период
Сортировка
От Bruce Momjian
Тема Re: SHARED locks barging behaviour
Дата
Msg-id ZRdFjrp7XOKpqi8e@momjian.us
обсуждение исходный текст
Ответ на SHARED locks barging behaviour  (Arul Ajmani <arula@cockroachlabs.com>)
Ответы Re: SHARED locks barging behaviour  (Laurenz Albe <laurenz.albe@cybertec.at>)
Список pgsql-hackers
On Tue, Jan 17, 2023 at 12:18:28PM -0500, Arul Ajmani wrote:
> I'm trying to better understand the following barging behaviour with SHARED
> locks.
...
> Given there is a transaction waiting to acquire a FOR UPDATE lock, I was
> surprised to see the second FOR SHARE transaction return immediately instead of
> waiting. I have two questions:
> 
> 1) Could this barging behaviour potentially starve out the transaction waiting
> to acquire the FOR UPDATE lock, if there is a continuous queue of transactions
> that acquire a FOR SHARE lock briefly?

Yes, see below.

> 2) Assuming this is by design, I couldn't find (in code) where this explicit
> policy choice is made. I was looking around LockAcquireExtended, but it seems
> like the decision is made above this layer. Could someone more familiar with
> this code point me at the right place? 

I know this from January, but I do have an answer.  First, looking at
parser/gram.y, I see:

            | FOR SHARE                         { $$ = LCS_FORSHARE; }

Looking for LCS_FORSHARE, I see in optimizer/plan/planner.c:

            case LCS_FORSHARE:
                return ROW_MARK_SHARE;

Looking for ROW_MARK_SHARE, I see in executor/nodeLockRows.c:

            case ROW_MARK_SHARE:
                lockmode = LockTupleShare;

Looking for LockTupleShare, I see in access/heap/heapam.c:

        else if (mode == LockTupleShare)
        {
            /*
             * If we're requesting Share, we can similarly avoid sleeping if
             * there's no update and no exclusive lock present.
             */
            if (HEAP_XMAX_IS_LOCKED_ONLY(infomask) &&
                !HEAP_XMAX_IS_EXCL_LOCKED(infomask))
            {
                LockBuffer(*buffer, BUFFER_LOCK_EXCLUSIVE);

                /*
                 * Make sure it's still an appropriate lock, else start over.
                 * See above about allowing xmax to change.
                 */
                if (!HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_data->t_infomask) ||
                    HEAP_XMAX_IS_EXCL_LOCKED(tuple->t_data->t_infomask))
                    goto l3;
                require_sleep = false;
            }
        }

and this is basically saying that if the row is locked
(HEAP_XMAX_IS_LOCKED_ONLY), but not exclusively locked
(!HEAP_XMAX_IS_EXCL_LOCKED), then there is no need to sleep waiting for
the lock.

I hope that helps.

-- 
  Bruce Momjian  <bruce@momjian.us>        https://momjian.us
  EDB                                      https://enterprisedb.com

  Only you can decide what is important to you.



В списке pgsql-hackers по дате отправления:

Предыдущее
От: Lakshmi Narayana Velayudam
Дата:
Сообщение: Implementing LRU cache for postgresql extension
Следующее
От: Peter Geoghegan
Дата:
Сообщение: Re: Eager page freeze criteria clarification