mirror of
https://github.com/postgres/postgres.git
synced 2025-05-06 19:59:18 +03:00
Allow relation extension lock to conflict among parallel group members.
This is required as it is no safer for two related processes to extend the same relation at a time than for unrelated processes to do the same. We don't acquire a heavyweight lock on any other object after relation extension lock which means such a lock can never participate in the deadlock cycle. So, avoid checking wait edges from this lock. This provides an infrastructure to allow parallel operations like insert, copy, etc. which were earlier not possible as parallel group members won't conflict for relation extension lock. Author: Dilip Kumar, Amit Kapila Reviewed-by: Amit Kapila, Kuntal Ghosh and Sawada Masahiko Discussion: https://postgr.es/m/CAD21AoCmT3cFQUN4aVvzy5chw7DuzXrJCbrjTU05B+Ss=Gn1LA@mail.gmail.com
This commit is contained in:
parent
b27e1b3418
commit
85f6b49c2c
@ -555,6 +555,14 @@ FindLockCycleRecurseMember(PGPROC *checkProc,
|
||||
int numLockModes,
|
||||
lm;
|
||||
|
||||
/*
|
||||
* The relation extension lock can never participate in actual deadlock
|
||||
* cycle. See Assert in LockAcquireExtended. So, there is no advantage
|
||||
* in checking wait edges from it.
|
||||
*/
|
||||
if (LOCK_LOCKTAG(*lock) == LOCKTAG_RELATION_EXTEND)
|
||||
return false;
|
||||
|
||||
lockMethodTable = GetLocksMethodTable(lock);
|
||||
numLockModes = lockMethodTable->numLockModes;
|
||||
conflictMask = lockMethodTable->conflictTab[checkProc->waitLockMode];
|
||||
|
@ -1469,6 +1469,16 @@ LockCheckConflicts(LockMethod lockMethodTable,
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* The relation extension lock conflict even between the group members.
|
||||
*/
|
||||
if (LOCK_LOCKTAG(*lock) == LOCKTAG_RELATION_EXTEND)
|
||||
{
|
||||
PROCLOCK_PRINT("LockCheckConflicts: conflicting (group)",
|
||||
proclock);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Locks held in conflicting modes by members of our own lock group are
|
||||
* not real conflicts; we can subtract those out and see if we still have
|
||||
|
@ -1077,7 +1077,13 @@ ProcSleep(LOCALLOCK *locallock, LockMethod lockMethodTable)
|
||||
|
||||
/*
|
||||
* If group locking is in use, locks held by members of my locking group
|
||||
* need to be included in myHeldLocks.
|
||||
* need to be included in myHeldLocks. This is not required for relation
|
||||
* extension lock which conflict among group members. However, including
|
||||
* them in myHeldLocks will give group members the priority to get those
|
||||
* locks as compared to other backends which are also trying to acquire
|
||||
* those locks. OTOH, we can avoid giving priority to group members for
|
||||
* that kind of locks, but there doesn't appear to be a clear advantage of
|
||||
* the same.
|
||||
*/
|
||||
if (leader != NULL)
|
||||
{
|
||||
|
@ -301,6 +301,7 @@ typedef struct LOCK
|
||||
} LOCK;
|
||||
|
||||
#define LOCK_LOCKMETHOD(lock) ((LOCKMETHODID) (lock).tag.locktag_lockmethodid)
|
||||
#define LOCK_LOCKTAG(lock) ((LockTagType) (lock).tag.locktag_type)
|
||||
|
||||
|
||||
/*
|
||||
|
Loading…
x
Reference in New Issue
Block a user