diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 6f30e08..e2c6274 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -86,6 +86,8 @@ static LOCALLOCK *lockAwaited = NULL; static DeadLockState deadlock_state = DS_NOT_YET_CHECKED; +static bool inside_deadlock_check = false; + /* Is a deadlock check pending? */ static volatile sig_atomic_t got_deadlock_timeout; @@ -187,6 +189,7 @@ InitProcGlobal(void) ProcGlobal->checkpointerLatch = NULL; pg_atomic_init_u32(&ProcGlobal->procArrayGroupFirst, INVALID_PGPROCNO); pg_atomic_init_u32(&ProcGlobal->clogGroupFirst, INVALID_PGPROCNO); + pg_atomic_init_flag(&ProcGlobal->activeDeadlockCheck); /* * Create and initialize all the PGPROC structures we'll need. There are @@ -763,6 +766,14 @@ ProcReleaseLocks(bool isCommit) { if (!MyProc) return; + + /* Release deadlock detection flag is backend was interrupted inside deadlock check */ + if (inside_deadlock_check) + { + pg_atomic_clear_flag(&ProcGlobal->activeDeadlockCheck); + inside_deadlock_check = false; + } + /* If waiting, get off wait queue (should only be needed after error) */ LockErrorCleanup(); /* Release standard locks, including session-level if aborting */ @@ -1666,6 +1677,18 @@ CheckDeadLock(void) { int i; + + /* + * Ensure that only one backend is checking for deadlock. + * Otherwise under high load cascade of deadlock timeout expirations can cause stuck of Postgres. + */ + if (!pg_atomic_test_set_flag(&ProcGlobal->activeDeadlockCheck)) + { + enable_timeout_after(DEADLOCK_TIMEOUT, DeadlockTimeout); + return; + } + inside_deadlock_check = true; + /* * Acquire exclusive lock on the entire shared lock data structures. Must * grab LWLocks in partition-number order to avoid LWLock deadlock. @@ -1741,6 +1764,9 @@ CheckDeadLock(void) check_done: for (i = NUM_LOCK_PARTITIONS; --i >= 0;) LWLockRelease(LockHashPartitionLockByIndex(i)); + + pg_atomic_clear_flag(&ProcGlobal->activeDeadlockCheck); + inside_deadlock_check = false; } /* diff --git a/src/include/storage/proc.h b/src/include/storage/proc.h index 5c19a61..04de570 100644 --- a/src/include/storage/proc.h +++ b/src/include/storage/proc.h @@ -267,6 +267,8 @@ typedef struct PROC_HDR int startupProcPid; /* Buffer id of the buffer that Startup process waits for pin on, or -1 */ int startupBufferPinWaitBufId; + /* Deadlock detection is in progress */ + pg_atomic_flag activeDeadlockCheck; } PROC_HDR; extern PGDLLIMPORT PROC_HDR *ProcGlobal;