Re: SHARED locks barging behaviour

From: Bruce Momjian <bruce(at)momjian(dot)us>
To: Arul Ajmani <arula(at)cockroachlabs(dot)com>
Cc: pgsql-hackers(at)postgresql(dot)org
Subject: Re: SHARED locks barging behaviour
Date: 2023-09-29 21:45:50
Message-ID: ZRdFjrp7XOKpqi8e@momjian.us
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: 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(at)momjian(dot)us> https://momjian.us
EDB https://enterprisedb.com

Only you can decide what is important to you.

In response to

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message Peter Geoghegan 2023-09-29 21:58:36 Re: Eager page freeze criteria clarification
Previous Message Lakshmi Narayana Velayudam 2023-09-29 20:56:57 Implementing LRU cache for postgresql extension