@@ -86,6 +86,8 @@ static LOCALLOCK *lockAwaited = NULL;
86
86
87
87
static DeadLockState deadlock_state = DS_NOT_YET_CHECKED ;
88
88
89
+ static bool inside_deadlock_check = false;
90
+
89
91
/* Is a deadlock check pending? */
90
92
static volatile sig_atomic_t got_deadlock_timeout ;
91
93
@@ -187,6 +189,7 @@ InitProcGlobal(void)
187
189
ProcGlobal -> checkpointerLatch = NULL ;
188
190
pg_atomic_init_u32 (& ProcGlobal -> procArrayGroupFirst , INVALID_PGPROCNO );
189
191
pg_atomic_init_u32 (& ProcGlobal -> clogGroupFirst , INVALID_PGPROCNO );
192
+ pg_atomic_init_flag (& ProcGlobal -> activeDeadlockCheck );
190
193
191
194
/*
192
195
* Create and initialize all the PGPROC structures we'll need. There are
@@ -763,6 +766,14 @@ ProcReleaseLocks(bool isCommit)
763
766
{
764
767
if (!MyProc )
765
768
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
+
766
777
/* If waiting, get off wait queue (should only be needed after error) */
767
778
LockErrorCleanup ();
768
779
/* Release standard locks, including session-level if aborting */
@@ -1665,6 +1676,21 @@ static void
1665
1676
CheckDeadLock (void )
1666
1677
{
1667
1678
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;
1668
1694
1669
1695
/*
1670
1696
* Acquire exclusive lock on the entire shared lock data structures. Must
@@ -1741,6 +1767,9 @@ CheckDeadLock(void)
1741
1767
check_done :
1742
1768
for (i = NUM_LOCK_PARTITIONS ; -- i >= 0 ;)
1743
1769
LWLockRelease (LockHashPartitionLockByIndex (i ));
1770
+
1771
+ pg_atomic_clear_flag (& ProcGlobal -> activeDeadlockCheck );
1772
+ inside_deadlock_check = false;
1744
1773
}
1745
1774
1746
1775
/*
0 commit comments