From 94921a2be119acbea1ddaea84979cbd55f6e8c19 Mon Sep 17 00:00:00 2001 From: Onder Kalaci Date: Thu, 9 Nov 2017 09:40:43 +0200 Subject: [PATCH] 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. --- .../distributed/transaction/lock_graph.c | 41 ++++++++++--------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/src/backend/distributed/transaction/lock_graph.c b/src/backend/distributed/transaction/lock_graph.c index 9d8af006f..cc05c72ba 100644 --- a/src/backend/distributed/transaction/lock_graph.c +++ b/src/backend/distributed/transaction/lock_graph.c @@ -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);