@@ -86,6 +86,8 @@ static LOCALLOCK *lockAwaited = NULL;
8686
8787static DeadLockState deadlock_state = DS_NOT_YET_CHECKED ;
8888
89+ static bool inside_deadlock_check = false;
90+
8991/* Is a deadlock check pending? */
9092static volatile sig_atomic_t got_deadlock_timeout ;
9193
@@ -187,6 +189,7 @@ InitProcGlobal(void)
187189 ProcGlobal -> checkpointerLatch = NULL ;
188190 pg_atomic_init_u32 (& ProcGlobal -> procArrayGroupFirst , INVALID_PGPROCNO );
189191 pg_atomic_init_u32 (& ProcGlobal -> clogGroupFirst , INVALID_PGPROCNO );
192+ pg_atomic_init_flag (& ProcGlobal -> activeDeadlockCheck );
190193
191194 /*
192195 * Create and initialize all the PGPROC structures we'll need. There are
@@ -763,6 +766,14 @@ ProcReleaseLocks(bool isCommit)
763766{
764767 if (!MyProc )
765768 return ;
769+
770+ /* Release deadlock detection flag is backend was interrupted inside deadlock check */
771+ if (inside_deadlock_check )
772+ {
773+ pg_atomic_clear_flag (& ProcGlobal -> activeDeadlockCheck );
774+ inside_deadlock_check = false;
775+ }
776+
766777 /* If waiting, get off wait queue (should only be needed after error) */
767778 LockErrorCleanup ();
768779 /* Release standard locks, including session-level if aborting */
@@ -1665,6 +1676,21 @@ static void
16651676CheckDeadLock (void )
16661677{
16671678 int i ;
1679+ TimestampTz now = GetCurrentTimestamp ();
1680+
1681+ if (now - MyProc -> lastDeadlockCheck < DeadlockTimeout * 1000 )
1682+ return ;
1683+
1684+ /*
1685+ * Ensure that only one backend is checking for deadlock.
1686+ * Otherwise under high load cascade of deadlock timeout expirations can cause stuck of Postgres.
1687+ */
1688+ if (!pg_atomic_test_set_flag (& ProcGlobal -> activeDeadlockCheck ))
1689+ {
1690+ enable_timeout_after (DEADLOCK_TIMEOUT , random () % DeadlockTimeout );
1691+ return ;
1692+ }
1693+ inside_deadlock_check = true;
16681694
16691695 /*
16701696 * Acquire exclusive lock on the entire shared lock data structures. Must
@@ -1741,6 +1767,9 @@ CheckDeadLock(void)
17411767check_done :
17421768 for (i = NUM_LOCK_PARTITIONS ; -- i >= 0 ;)
17431769 LWLockRelease (LockHashPartitionLockByIndex (i ));
1770+
1771+ pg_atomic_clear_flag (& ProcGlobal -> activeDeadlockCheck );
1772+ inside_deadlock_check = false;
17441773}
17451774
17461775/*
0 commit comments