mirror of https://github.com/citusdata/citus.git
Merge pull request #1670 from citusdata/remove_unnecessary_locks_in_graph
Skip relation extension locks on distributed deadlock detectionpull/1667/head
commit
b2d42a0595
|
@ -49,6 +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 void LockLockData(void);
|
||||
static void UnlockLockData(void);
|
||||
static void AddEdgesForLockWaits(WaitGraph *waitGraph, PGPROC *waitingProc,
|
||||
|
@ -447,6 +448,12 @@ BuildLocalWaitGraph(void)
|
|||
continue;
|
||||
}
|
||||
|
||||
/* skip if the process is blocked for relation extension */
|
||||
if (IsProcessWaitingForRelationExtension(currentProc))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
AddProcToVisit(&remaining, currentProc);
|
||||
}
|
||||
|
||||
|
@ -460,6 +467,12 @@ BuildLocalWaitGraph(void)
|
|||
continue;
|
||||
}
|
||||
|
||||
/* skip if the process is blocked for relation extension */
|
||||
if (IsProcessWaitingForRelationExtension(waitingProc))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Record an edge for everyone already holding the lock in a
|
||||
* conflicting manner ("hard edges" in postgres parlance).
|
||||
|
@ -479,6 +492,36 @@ BuildLocalWaitGraph(void)
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
* IsProcessWaitingForRelationExtension returns true if the given PROC
|
||||
* waiting on relation extension lock.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
static bool
|
||||
IsProcessWaitingForRelationExtension(PGPROC *proc)
|
||||
{
|
||||
PROCLOCK *waitProcLock = NULL;
|
||||
LOCK *waitLock = NULL;
|
||||
|
||||
if (proc->waitStatus != STATUS_WAITING)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
waitProcLock = proc->waitProcLock;
|
||||
waitLock = waitProcLock->tag.myLock;
|
||||
|
||||
return waitLock->tag.locktag_type == LOCKTAG_RELATION_EXTEND;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* LockLockData takes locks the shared lock data structure, which prevents
|
||||
* concurrent lock acquisitions/releases.
|
||||
|
@ -550,9 +593,14 @@ AddEdgesForLockWaits(WaitGraph *waitGraph, PGPROC *waitingProc, PROCStack *remai
|
|||
{
|
||||
PGPROC *currentProc = procLock->tag.myProc;
|
||||
|
||||
/* skip processes from the same lock group and ones that don't conflict */
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
if (!IsSameLockGroup(waitingProc, currentProc) &&
|
||||
IsConflictingLockMask(procLock->holdMask, conflictMask))
|
||||
IsConflictingLockMask(procLock->holdMask, conflictMask) &&
|
||||
!IsProcessWaitingForRelationExtension(currentProc))
|
||||
{
|
||||
AddWaitEdge(waitGraph, waitingProc, currentProc, remaining);
|
||||
}
|
||||
|
@ -590,9 +638,14 @@ AddEdgesForWaitQueue(WaitGraph *waitGraph, PGPROC *waitingProc, PROCStack *remai
|
|||
{
|
||||
int awaitMask = LOCKBIT_ON(currentProc->waitLockMode);
|
||||
|
||||
/* skip processes from the same lock group and ones that don't conflict */
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
if (!IsSameLockGroup(waitingProc, currentProc) &&
|
||||
IsConflictingLockMask(awaitMask, conflictMask))
|
||||
IsConflictingLockMask(awaitMask, conflictMask) &&
|
||||
!IsProcessWaitingForRelationExtension(currentProc))
|
||||
{
|
||||
AddWaitEdge(waitGraph, waitingProc, currentProc, remaining);
|
||||
}
|
||||
|
@ -621,7 +674,9 @@ AddWaitEdge(WaitGraph *waitGraph, PGPROC *waitingProc, PGPROC *blockingProc,
|
|||
GetBackendDataForProc(waitingProc, &waitingBackendData);
|
||||
GetBackendDataForProc(blockingProc, &blockingBackendData);
|
||||
|
||||
curEdge->isBlockingXactWaiting = IsProcessWaitingForLock(blockingProc);
|
||||
curEdge->isBlockingXactWaiting =
|
||||
IsProcessWaitingForLock(blockingProc) &&
|
||||
!IsProcessWaitingForRelationExtension(blockingProc);
|
||||
if (curEdge->isBlockingXactWaiting)
|
||||
{
|
||||
AddProcToVisit(remaining, blockingProc);
|
||||
|
|
Loading…
Reference in New Issue