diff --git a/mysql-test/main/lock_kill.result b/mysql-test/main/lock_kill.result new file mode 100644 index 0000000000000..727dd66da7ff4 --- /dev/null +++ b/mysql-test/main/lock_kill.result @@ -0,0 +1,36 @@ +# +# MDEV-17749 Kill during LOCK TABLE ; ALTER TABLE causes assert +# +CREATE TABLE t1 (a INT) ENGINE=InnoDB; +connect con1,localhost,root,,test; +LOCK TABLE t1 WRITE; +ALTER TABLE t1 ADD COLUMN b INT; +connection default; +Killing connection +connection con1; +connection default; +disconnect con1; +DROP TABLE t1; +CREATE TABLE t1 (a INT) ENGINE=InnoDB; +CREATE TABLE t2 (a INT) ENGINE=InnoDB; +connect con1,localhost,root,,test; +LOCK TABLE t1 WRITE, t2 WRITE; +ALTER TABLE t1 ADD COLUMN b INT; +connection default; +Killing connection +connection con1; +connection default; +disconnect con1; +DROP TABLE t1, t2; +CREATE TABLE t1 (id int(11)) ENGINE=InnoDB; +LOCK TABLES t1 WRITE; +SET max_statement_time= 0.0001; +CREATE TRIGGER tr16 AFTER UPDATE ON t1 FOR EACH ROW INSERT INTO t1 VALUES (1); +SET max_statement_time= default; +DROP TRIGGER IF EXISTS trg16; +Warnings: +Note 1360 Trigger does not exist +DROP TABLE t1; +# +# End of 10.3 tests +# diff --git a/mysql-test/main/lock_kill.test b/mysql-test/main/lock_kill.test new file mode 100644 index 0000000000000..d0b83fe14132e --- /dev/null +++ b/mysql-test/main/lock_kill.test @@ -0,0 +1,59 @@ +--source include/have_innodb.inc + +# This test file is for testing killing of queries that are under LOCK TABLES + +--echo # +--echo # MDEV-17749 Kill during LOCK TABLE ; ALTER TABLE causes assert +--echo # + +CREATE TABLE t1 (a INT) ENGINE=InnoDB; +--connect (con1,localhost,root,,test) +LOCK TABLE t1 WRITE; +--let $conid= `SELECT CONNECTION_ID()` +--send ALTER TABLE t1 ADD COLUMN b INT +--connection default +--disable_query_log +--echo Killing connection +eval KILL $conid; +--enable_query_log +--connection con1 +--error 0,2013 +reap; +--connection default +--disconnect con1 +DROP TABLE t1; + +CREATE TABLE t1 (a INT) ENGINE=InnoDB; +CREATE TABLE t2 (a INT) ENGINE=InnoDB; +--connect (con1,localhost,root,,test) +LOCK TABLE t1 WRITE, t2 WRITE; +--let $conid= `SELECT CONNECTION_ID()` +--send ALTER TABLE t1 ADD COLUMN b INT +--connection default +--disable_query_log +--echo Killing connection +eval KILL $conid; +--enable_query_log +--connection con1 +--error 0,2013 +reap; +--connection default +--disconnect con1 +DROP TABLE t1, t2; + +# Similar test for CREATE TRIGGER, which also failed + +CREATE TABLE t1 (id int(11)) ENGINE=InnoDB; +LOCK TABLES t1 WRITE; +SET max_statement_time= 0.0001; +--error 0,1969 +--disable_warnings +CREATE TRIGGER tr16 AFTER UPDATE ON t1 FOR EACH ROW INSERT INTO t1 VALUES (1); +--enable_warnings +SET max_statement_time= default; +DROP TRIGGER IF EXISTS trg16; +DROP TABLE t1; + +--echo # +--echo # End of 10.3 tests +--echo # diff --git a/sql/sql_base.cc b/sql/sql_base.cc index f793556cf6297..e80a78ff802cf 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -2469,7 +2469,17 @@ unlink_all_closed_tables(THD *thd, MYSQL_LOCK *lock, size_t reopen_count) /* If no tables left, do an automatic UNLOCK TABLES */ if (thd->lock && thd->lock->table_count == 0) + { + /* + We have to rollback any open transactions here. + This is required in the case where the server has been killed + but some transations are still open (as part of locked tables). + If we don't do this, we will get an assert in unlock_locked_tables(). + */ + ha_rollback_trans(thd, FALSE); + ha_rollback_trans(thd, TRUE); unlock_locked_tables(thd); + } }