diff --git a/mysql-test/main/deadlock_ftwrl.result b/mysql-test/main/deadlock_ftwrl.result new file mode 100644 index 00000000000..95eed70f664 --- /dev/null +++ b/mysql-test/main/deadlock_ftwrl.result @@ -0,0 +1,21 @@ +CREATE TABLE t1(a INT); +SELECT GET_LOCK("l1", 0); +GET_LOCK("l1", 0) +1 +connect con1,localhost,root,,; +LOCK TABLES t1 WRITE; +connection default; +set debug_sync='mdl_acquire_lock_wait SIGNAL ftwrl'; +FLUSH TABLES WITH READ LOCK; +connection con1; +set debug_sync='now WAIT_FOR ftwrl'; +SELECT GET_LOCK("l1", 1000); +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +disconnect con1; +connection default; +SELECT RELEASE_LOCK("l1"); +RELEASE_LOCK("l1") +1 +UNLOCK TABLES; +DROP TABLE t1; +set debug_sync='reset'; diff --git a/mysql-test/main/deadlock_ftwrl.test b/mysql-test/main/deadlock_ftwrl.test new file mode 100644 index 00000000000..fc943bcf953 --- /dev/null +++ b/mysql-test/main/deadlock_ftwrl.test @@ -0,0 +1,36 @@ +# MDEV-20946 Hard FTWRL deadlock under user level locks +# +# Deadlock detector should resolve conflicts between FTWRL and user locks. + +--source include/have_debug_sync.inc +--source include/count_sessions.inc + +CREATE TABLE t1(a INT); +SELECT GET_LOCK("l1", 0); + +connect(con1,localhost,root,,); +LOCK TABLES t1 WRITE; + +connection default; +set debug_sync='mdl_acquire_lock_wait SIGNAL ftwrl'; +send FLUSH TABLES WITH READ LOCK; +# At this point "default" is waiting for tables to be unlocked from +# LOCK TABLES WRITE issued by "con1". + +connection con1; +set debug_sync='now WAIT_FOR ftwrl'; +# The lock in the following GET_LOCK cannot be acquired since "default" holds +# a lock on "l1" and is waiting in FLUSH TABLES for con1. +--error ER_LOCK_DEADLOCK +SELECT GET_LOCK("l1", 1000); +disconnect con1; # Performs an implicit UNLOCK TABLES. + +connection default; +reap; +SELECT RELEASE_LOCK("l1"); +UNLOCK TABLES; +DROP TABLE t1; + +set debug_sync='reset'; + +--source include/wait_until_count_sessions.inc diff --git a/sql/mdl.cc b/sql/mdl.cc index 1798d3039fa..5e54178db70 100644 --- a/sql/mdl.cc +++ b/sql/mdl.cc @@ -2782,6 +2782,7 @@ void MDL_context::find_deadlock() context was waiting is concurrently satisfied. */ (void) victim->m_wait.set_status(MDL_wait::VICTIM); + victim->inc_deadlock_overweight(); victim->unlock_deadlock_victim(); if (victim == this) diff --git a/sql/mdl.h b/sql/mdl.h index 9a788b0ea31..a2cb7c2aa85 100644 --- a/sql/mdl.h +++ b/sql/mdl.h @@ -909,7 +909,8 @@ public: /** @pre Only valid if we started waiting for lock. */ inline uint get_deadlock_weight() const - { return m_waiting_for->get_deadlock_weight(); } + { return m_waiting_for->get_deadlock_weight() + m_deadlock_overweight; } + void inc_deadlock_overweight() { m_deadlock_overweight++; } /** Post signal to the context (and wake it up if necessary). @@ -1027,6 +1028,7 @@ private: */ MDL_wait_for_subgraph *m_waiting_for; LF_PINS *m_pins; + uint m_deadlock_overweight= 0; private: MDL_ticket *find_ticket(MDL_request *mdl_req, enum_mdl_duration *duration);