Re: [PATCH] LockAcquireExtended improvement

Andres Freund <andres@anarazel.de>

From: Andres Freund <andres@anarazel.de>
To: Jingxian Li <aqktjcm@qq.com>
Cc: "PostgreSQL&nbsp;Hackers" <pgsql-hackers@lists.postgresql.org>
Date: 2023-11-28T16:51:39Z
Lists: pgsql-hackers
Hi,

On 2023-11-28 20:52:31 +0800, Jingxian Li wrote:
> postgres=*# lock table test in exclusive mode ;
>
>
> T4
>
> Case 1:
>
> postgres=*# lock table test in share row exclusive mode   nowait;
>
> ERROR: &nbsp;could not   obtain lock on relation "test"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
>
> --------------------------------------------
>
> Case 2:
>
> postgres=*# lock table test in share row exclusive mode;
>
> LOCK TABLE
>
> &nbsp;
>
>
> At T4 moment in session A, (case 1) when executing SQL “lock table test in share row exclusive mode nowait;”, an error occurs with message “could not obtain lock on relation test";However, (case 2) when executing the SQL above without nowait, lock can be obtained successfully.
>
> Digging into the source code, I find that in case 2 the lock was obtained in
> the function ProcSleep instead of LockAcquireExtended. Due to nowait logic
> processed before WaitOnLock-&gt;ProcSleep, acquiring lock failed in case
> 1. Can any changes be made so that the act of such lock granted occurs
> before WaitOnLock?

I don't think that'd make sense - lock reordering is done to prevent deadlocks
and is quite expensive. Why should NOWAIT incur that cost?


> &nbsp;
>
> Providing a more universal case:
>
> Transaction A already holds an n-mode lock on table test. If then transaction A requests an m-mode lock on table Test, m and n have the following constraints:
>
> (lockMethodTable-&gt;conflictTab[n] &amp; lockMethodTable-&gt;conflictTab[m]) == lockMethodTable-&gt;conflictTab[m]
>
> Obviously, in this case, m<=n.
>
> Should the m-mode lock be granted before WaitOnLock?
>
> &nbsp;
>
> In the case of m=n (i.e. we already hold the lock), the m-mode lock is
> immediately granted in the LocalLock path, without the need of lock conflict
> check.

Sure - it'd not help anybody to wait for a lock we already hold - in fact it'd
create a lot of deadlocks.


> Based on the facts above, can we obtain a weaker lock (m<n) on the same
> object within the same transaction without doing lock conflict check?

Perhaps. There's no inherent "lock strength" ordering for all locks though.

Greetings,

Andres Freund



Commits

  1. Fix typo and comments related to the recent no-wait lock improvements

  2. Allow a no-wait lock acquisition to succeed in more cases.