commit d80207e743b4691a2f687b6ad2bf8be3b21515b8 Author: Laurynas Biveinis Date: Thu Jun 1 17:10:45 2017 +0300 Fix bug 77399 / 1466414 (Deadlocks missed by INFORMATION_SCHEMA.INNODB_METRICS lock_deadlocks counter) In case the joining transaction is selected as the deadlock victim, the InnoDB metrics deadlock counter will not be bumped. Fix by adding a bump there, and removing the bump in the search-too-deep code path to compensate for this case. diff --git a/mysql-test/suite/innodb/r/innodb_deadlock_count.result b/mysql-test/suite/innodb/r/innodb_deadlock_count.result new file mode 100644 index 00000000000..3a88f9be334 --- /dev/null +++ b/mysql-test/suite/innodb/r/innodb_deadlock_count.result @@ -0,0 +1,32 @@ +# +# Bug 77399: Deadlocks missed by INFORMATION_SCHEMA.INNODB_METRICS lock_deadlocks counter +# +# Establish connection con1 (user=root) +# Establish connection con2 (user=root) +# Create test table +create table t(a INT PRIMARY KEY, b INT) engine=InnoDB; +# Insert two rows to test table +insert into t values(2,1); +insert into t values(1,2); +SELECT COUNT INTO @start_metrics_val +FROM INFORMATION_SCHEMA.INNODB_METRICS WHERE NAME='lock_deadlocks'; +# Switch to connection con1 +BEGIN; +SELECT b FROM t WHERE a=1 FOR UPDATE; +# Switch to connection con2 +BEGIN; +SELECT b FROM t WHERE a=2 FOR UPDATE; +# Switch to connection con1 +SELECT b FROM t WHERE a=2 FOR UPDATE; +# Switch to connection con2 +SELECT b FROM t WHERE a=1 FOR UPDATE; +# Switch to connection con1 +ROLLBACK; +# Switch to connection con2 +ROLLBACK; +# Switch to connection default +SELECT COUNT INTO @lock_deadlocks_var FROM INFORMATION_SCHEMA.INNODB_METRICS WHERE NAME='lock_deadlocks'; +include/assert.inc [Exactly one deadlock should have been found] +# Drop test table +drop table t; +SET GLOBAL innodb_monitor_reset = default; diff --git a/mysql-test/suite/innodb/t/innodb_deadlock_count.test b/mysql-test/suite/innodb/t/innodb_deadlock_count.test new file mode 100644 index 00000000000..3b7c3e2feff --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb_deadlock_count.test @@ -0,0 +1,71 @@ +--echo # +--echo # Bug 77399: Deadlocks missed by INFORMATION_SCHEMA.INNODB_METRICS lock_deadlocks counter +--echo # + +--source include/count_sessions.inc + +--echo # Establish connection con1 (user=root) +connect (con1,localhost,root,,); +--echo # Establish connection con2 (user=root) +connect (con2,localhost,root,,); + +--echo # Create test table +create table t(a INT PRIMARY KEY, b INT) engine=InnoDB; +--echo # Insert two rows to test table +insert into t values(2,1); +insert into t values(1,2); + +connection default; +SELECT COUNT INTO @start_metrics_val + FROM INFORMATION_SCHEMA.INNODB_METRICS WHERE NAME='lock_deadlocks'; + +--disable_result_log + +--echo # Switch to connection con1 +connection con1; +BEGIN; SELECT b FROM t WHERE a=1 FOR UPDATE; + +--echo # Switch to connection con2 +connection con2; +BEGIN; SELECT b FROM t WHERE a=2 FOR UPDATE; + +--echo # Switch to connection con1 +connection con1; +SEND SELECT b FROM t WHERE a=2 FOR UPDATE; + +--echo # Switch to connection con2 +connection con2; +SEND SELECT b FROM t WHERE a=1 FOR UPDATE; + +--echo # Switch to connection con1 +connection con1; +--error 0, ER_LOCK_DEADLOCK +reap; +ROLLBACK; + +--echo # Switch to connection con2 +connection con2; +--error 0, ER_LOCK_DEADLOCK +reap; +ROLLBACK; + +--echo # Switch to connection default +connection default; +--enable_result_log + +--disconnect con1 +--disconnect con2 + +SELECT COUNT INTO @lock_deadlocks_var FROM INFORMATION_SCHEMA.INNODB_METRICS WHERE NAME='lock_deadlocks'; +--let $assert_text= Exactly one deadlock should have been found +--let $assert_cond= @lock_deadlocks_var - @start_metrics_val = 1 +--source include/assert.inc + +--echo # Drop test table +drop table t; + +--disable_warnings +SET GLOBAL innodb_monitor_reset = default; +--enable_warnings + +--source include/wait_until_count_sessions.inc diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc index eed5b6b8eb3..c9a197ece37 100644 --- a/storage/innobase/lock/lock0lock.cc +++ b/storage/innobase/lock/lock0lock.cc @@ -7489,8 +7489,6 @@ DeadlockChecker::check_and_resolve(const lock_t* lock, trx_t* trx) rollback_print(victim_trx, lock); - MONITOR_INC(MONITOR_DEADLOCK); - break; } else if (victim_trx != NULL && victim_trx != trx) { @@ -7512,6 +7510,8 @@ DeadlockChecker::check_and_resolve(const lock_t* lock, trx_t* trx) print("*** WE ROLL BACK TRANSACTION (2)\n"); lock_deadlock_found = true; + + MONITOR_INC(MONITOR_DEADLOCK); } trx_mutex_enter(trx);