Re: [PATCH] LockAcquireExtended improvement - Mailing list pgsql-hackers
From | Jingxian Li |
---|---|
Subject | Re: [PATCH] LockAcquireExtended improvement |
Date | |
Msg-id | tencent_11D01D86DFF79B0A300BC1C7A4B6F0D9790A@qq.com Whole thread Raw |
In response to | [PATCH] LockAcquireExtended improvement ("Jingxian Li" <aqktjcm@qq.com>) |
Responses |
Re: [PATCH] LockAcquireExtended improvement
|
List | pgsql-hackers |
Hi Andres, Thanks for your quick reply! On 2023/11/29 0:51, Andres Freund wrote: > 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: could not obtain lock on relation "test" >> >> -------------------------------------------- >> >> Case 2: >> >> postgres=*# lock table test in share row exclusive mode; >> >> LOCK TABLE >> >> >> >> At T4 moment in session A, (case 1) when executing SQL “lock table test in share row exclusive mode nowait;”, an erroroccurs with message “could not obtain lock on relation test";However, (case 2) when executing the SQL above withoutnowait, 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->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? > > >> >> 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->conflictTab[n] & lockMethodTable->conflictTab[m]) == lockMethodTable->conflictTab[m] >> >> Obviously, in this case, m<=n. >> >> Should the m-mode lock be granted before WaitOnLock? >> >> >> 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. I also noticed that there is no inherent "lock strength" orderingfor all locks. So I use the following method in the code to determine the strength of the lock: if (m<n &&(lockMethodTable->conflictTab[n] & lockMethodTable->conflictTab[m]) == lockMethodTable->conflictTab[m]) then we can say that m-mode lock is weaker than n-mode lock. Transaction A already holds an n-mode lock on table test, that is, there is no locks held conflicting with the n-mode lock on table test, If then transaction A requests an m-mode lock on table test, as n's confilctTab covers m, it can be concluded that there are no locks conflicting with the requested m-mode lock. > > Greetings, > > Andres Freund > With regards, Jingxian Li
pgsql-hackers by date: