From a5e268a2931c39c7b3cc2ff2e6e3fe6b5e85a383 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 22 Jul 2019 14:55:46 +0300 Subject: [PATCH] MDEV-20102 Phantom InnoDB table remains after interrupted CREATE...SELECT This is a regression due to MDEV-16515 that affects some versions in the MariaDB 10.1 server series starting with 10.1.35, and possibly all versions starting with 10.2.17, 10.3.8, and 10.4.0. The idea of MDEV-16515 is to allow DROP TABLE to be interrupted, in case it was stuck due to some concurrent activity. We already made some cases of internal DROP TABLE immune to kill in MDEV-18237, MDEV-16647, MDEV-17470. We must include the cleanup of CREATE TABLE...SELECT in the list of such internal DROP TABLE. ha_innobase::delete_table(): Pass create_failed=true if the current SQL statement is CREATE, so that the table will be dropped. row_drop_table_for_mysql(): If create_failed=true, do not allow the operation to be interrupted. --- .../suite/innodb/r/create_select.result | 5 ++++ mysql-test/suite/innodb/t/create_select.test | 28 +++++++++++++++++++ storage/innobase/handler/ha_innodb.cc | 12 ++++---- storage/innobase/include/row0mysql.h | 3 +- storage/innobase/row/row0mysql.cc | 7 +++-- storage/xtradb/handler/ha_innodb.cc | 12 ++++---- storage/xtradb/include/row0mysql.h | 4 +-- storage/xtradb/row/row0mysql.cc | 7 +++-- 8 files changed, 59 insertions(+), 19 deletions(-) create mode 100644 mysql-test/suite/innodb/r/create_select.result create mode 100644 mysql-test/suite/innodb/t/create_select.test diff --git a/mysql-test/suite/innodb/r/create_select.result b/mysql-test/suite/innodb/r/create_select.result new file mode 100644 index 00000000000..35acb2e265a --- /dev/null +++ b/mysql-test/suite/innodb/r/create_select.result @@ -0,0 +1,5 @@ +CREATE TABLE t1 ENGINE=InnoDB SELECT * FROM seq_1_to_100000000; +KILL QUERY @id; +ERROR 70100: Query execution was interrupted +CREATE TABLE t1 (a SERIAL) ENGINE=InnoDB; +DROP TABLE t1; diff --git a/mysql-test/suite/innodb/t/create_select.test b/mysql-test/suite/innodb/t/create_select.test new file mode 100644 index 00000000000..8103902e5f6 --- /dev/null +++ b/mysql-test/suite/innodb/t/create_select.test @@ -0,0 +1,28 @@ +--source include/have_innodb.inc +--source include/have_sequence.inc +--source include/count_sessions.inc + +let $ID= `SELECT @id := CONNECTION_ID()`; + +connect (con1, localhost, root,,); +let $ignore= `SELECT @id := $ID`; + +connection default; +send CREATE TABLE t1 ENGINE=InnoDB SELECT * FROM seq_1_to_100000000; + +connection con1; +let $wait_condition= + select count(*) = 1 from information_schema.processlist + where state = 'Sending data' + and info = 'CREATE TABLE t1 ENGINE=InnoDB SELECT * FROM seq_1_to_100000000'; +--source include/wait_condition.inc +KILL QUERY @id; +disconnect con1; + +connection default; +--error ER_QUERY_INTERRUPTED +reap; + +CREATE TABLE t1 (a SERIAL) ENGINE=InnoDB; +DROP TABLE t1; +--source include/wait_until_count_sessions.inc diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index e04d431174a..de9096c8fcb 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -12645,11 +12645,12 @@ ha_innobase::delete_table( ++trx->will_lock; trx->ddl = true; + const int sqlcom = thd_sql_command(thd); + /* Drop the table in InnoDB */ err = row_drop_table_for_mysql( - norm_name, trx, thd_sql_command(thd) == SQLCOM_DROP_DB, - FALSE); - + norm_name, trx, sqlcom == SQLCOM_DROP_DB, + sqlcom == SQLCOM_CREATE_TABLE /* CREATE TABLE ... SELECT */); if (err == DB_TABLE_NOT_FOUND && innobase_get_lower_case_table_names() == 1) { @@ -12679,8 +12680,9 @@ ha_innobase::delete_table( #endif err = row_drop_table_for_mysql( par_case_name, trx, - thd_sql_command(thd) == SQLCOM_DROP_DB, - FALSE); + sqlcom == SQLCOM_DROP_DB, + sqlcom == SQLCOM_CREATE_TABLE + /* CREATE TABLE ... SELECT */); } } diff --git a/storage/innobase/include/row0mysql.h b/storage/innobase/include/row0mysql.h index a8a228e6b2b..2069caf7f3f 100644 --- a/storage/innobase/include/row0mysql.h +++ b/storage/innobase/include/row0mysql.h @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 2000, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2015, 2019, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -491,7 +492,7 @@ row_drop_table_for_mysql( const char* name, /*!< in: table name */ trx_t* trx, /*!< in: dictionary transaction handle */ bool drop_db,/*!< in: true=dropping whole database */ - ibool create_failed,/*!will_lock; trx->ddl = true; + const int sqlcom = thd_sql_command(thd); + /* Drop the table in InnoDB */ err = row_drop_table_for_mysql( - norm_name, trx, thd_sql_command(thd) == SQLCOM_DROP_DB, - FALSE); - + norm_name, trx, sqlcom == SQLCOM_DROP_DB, + sqlcom == SQLCOM_CREATE_TABLE /* CREATE TABLE ... SELECT */); if (err == DB_TABLE_NOT_FOUND && innobase_get_lower_case_table_names() == 1) { @@ -13253,8 +13254,9 @@ ha_innobase::delete_table( #endif err = row_drop_table_for_mysql( par_case_name, trx, - thd_sql_command(thd) == SQLCOM_DROP_DB, - FALSE); + sqlcom == SQLCOM_DROP_DB, + sqlcom == SQLCOM_CREATE_TABLE + /* CREATE TABLE ... SELECT */); } } diff --git a/storage/xtradb/include/row0mysql.h b/storage/xtradb/include/row0mysql.h index b71f5e2103e..6580596550e 100644 --- a/storage/xtradb/include/row0mysql.h +++ b/storage/xtradb/include/row0mysql.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2000, 2017, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, MariaDB Corporation. +Copyright (c) 2017, 2019, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -493,7 +493,7 @@ row_drop_table_for_mysql( const char* name, /*!< in: table name */ trx_t* trx, /*!< in: dictionary transaction handle */ bool drop_db,/*!< in: true=dropping whole database */ - ibool create_failed,/*!