Skip page-level locks on distributed deadlock detection

Short-term share/exclusive page-level locks are used for
read/write access. Locks are released immediately after
each index row is fetched or inserted.

Since those locks may not lead to any deadlocks, it's safe
to ignore them in the distributed deadlock detection.
pull/1777/head
Onder Kalaci 2017-11-09 09:40:43 +02:00
parent a85a973c3e
commit 94921a2be1
1 changed files with 21 additions and 20 deletions

View File

@ -49,7 +49,7 @@ static bool ParseBoolField(PGresult *result, int rowIndex, int colIndex);
static TimestampTz ParseTimestampTzField(PGresult *result, int rowIndex, int colIndex);
static void ReturnWaitGraph(WaitGraph *waitGraph, FunctionCallInfo fcinfo);
static WaitGraph * BuildLocalWaitGraph(void);
static bool IsProcessWaitingForRelationExtension(PGPROC *proc);
static bool IsProcessWaitingForSafeOperations(PGPROC *proc);
static void LockLockData(void);
static void UnlockLockData(void);
static void AddEdgesForLockWaits(WaitGraph *waitGraph, PGPROC *waitingProc,
@ -449,7 +449,7 @@ BuildLocalWaitGraph(void)
}
/* skip if the process is blocked for relation extension */
if (IsProcessWaitingForRelationExtension(currentProc))
if (IsProcessWaitingForSafeOperations(currentProc))
{
continue;
}
@ -468,7 +468,7 @@ BuildLocalWaitGraph(void)
}
/* skip if the process is blocked for relation extension */
if (IsProcessWaitingForRelationExtension(waitingProc))
if (IsProcessWaitingForSafeOperations(waitingProc))
{
continue;
}
@ -493,19 +493,19 @@ BuildLocalWaitGraph(void)
/*
* IsProcessWaitingForRelationExtension returns true if the given PROC
* waiting on relation extension lock.
* IsProcessWaitingForSafeOperations returns true if the given PROC
* waiting on relation extension lock or page locks.
*
* In general for the purpose of distributed deadlock detection, we should
* skip if the process blocked on the relation extension. Those locks are
* held for a short duration while the relation is actually extended on
* the disk and released as soon as the extension is done, even before the
* execution of the command that triggered the extension finishes. Thus,
* recording such waits on our lock graphs could yield detecting wrong
* distributed deadlocks.
* skip if the process blocked on the locks that may not be part of deadlocks.
* Those locks are held for a short duration while the relation or the index
* is actually extended on the disk and released as soon as the extension is
* done, even before the execution of the command that triggered the extension
* finishes. Thus, recording such waits on our lock graphs could yield detecting
* wrong distributed deadlocks.
*/
static bool
IsProcessWaitingForRelationExtension(PGPROC *proc)
IsProcessWaitingForSafeOperations(PGPROC *proc)
{
PROCLOCK *waitProcLock = NULL;
LOCK *waitLock = NULL;
@ -518,7 +518,8 @@ IsProcessWaitingForRelationExtension(PGPROC *proc)
waitProcLock = proc->waitProcLock;
waitLock = waitProcLock->tag.myLock;
return waitLock->tag.locktag_type == LOCKTAG_RELATION_EXTEND;
return waitLock->tag.locktag_type == LOCKTAG_RELATION_EXTEND ||
waitLock->tag.locktag_type == LOCKTAG_PAGE;
}
@ -595,12 +596,12 @@ AddEdgesForLockWaits(WaitGraph *waitGraph, PGPROC *waitingProc, PROCStack *remai
/*
* Skip processes from the same lock group, processes that don't conflict,
* and processes that are waiting on a relation extension lock, which
* will be released shortly.
* and processes that are waiting on a relation extension lock or page locks,
* which will be released shortly.
*/
if (!IsSameLockGroup(waitingProc, currentProc) &&
IsConflictingLockMask(procLock->holdMask, conflictMask) &&
!IsProcessWaitingForRelationExtension(currentProc))
!IsProcessWaitingForSafeOperations(currentProc))
{
AddWaitEdge(waitGraph, waitingProc, currentProc, remaining);
}
@ -640,12 +641,12 @@ AddEdgesForWaitQueue(WaitGraph *waitGraph, PGPROC *waitingProc, PROCStack *remai
/*
* Skip processes from the same lock group, processes that don't conflict,
* and processes that are waiting on a relation extension lock, which
* will be released shortly.
* and processes that are waiting on a relation extension lock or page locks,
* which will be released shortly.
*/
if (!IsSameLockGroup(waitingProc, currentProc) &&
IsConflictingLockMask(awaitMask, conflictMask) &&
!IsProcessWaitingForRelationExtension(currentProc))
!IsProcessWaitingForSafeOperations(currentProc))
{
AddWaitEdge(waitGraph, waitingProc, currentProc, remaining);
}
@ -676,7 +677,7 @@ AddWaitEdge(WaitGraph *waitGraph, PGPROC *waitingProc, PGPROC *blockingProc,
curEdge->isBlockingXactWaiting =
IsProcessWaitingForLock(blockingProc) &&
!IsProcessWaitingForRelationExtension(blockingProc);
!IsProcessWaitingForSafeOperations(blockingProc);
if (curEdge->isBlockingXactWaiting)
{
AddProcToVisit(remaining, blockingProc);