From c5a5eaa9a996015517c1ebbce19551c6e650cba1 Mon Sep 17 00:00:00 2001 From: Eugene Kosov Date: Fri, 14 Dec 2018 01:28:55 +0300 Subject: [PATCH] MDEV-17470 Orphan temporary files after interrupted ALTER cause InnoDB: Operating system error number 17 and eventual fatal error 71 Orphan #sql* tables may remain after ALTER TABLE was interrupted by timeout or KILL or client disconnect. This is a regression caused by MDEV-16515. Similar to temporary tables (MDEV-16647), we had better ignore the KILL when dropping the original table in the final part of ALTER TABLE. Closes #1020 --- .../suite/innodb/r/innodb-alter-debug.result | 21 ++++++++++++++ .../suite/innodb/t/innodb-alter-debug.test | 28 +++++++++++++++++++ storage/innobase/row/row0mysql.cc | 5 ++-- storage/xtradb/row/row0mysql.cc | 5 ++-- 4 files changed, 55 insertions(+), 4 deletions(-) diff --git a/mysql-test/suite/innodb/r/innodb-alter-debug.result b/mysql-test/suite/innodb/r/innodb-alter-debug.result index d888fb5b034..5ce93b96c77 100644 --- a/mysql-test/suite/innodb/r/innodb-alter-debug.result +++ b/mysql-test/suite/innodb/r/innodb-alter-debug.result @@ -68,3 +68,24 @@ SET DEBUG_SYNC = 'now SIGNAL S2'; ERROR 23000: Duplicate entry '1' for key 'a' SET DEBUG_SYNC='RESET'; DROP TABLE t1; +# +# MDEV-17470 Orphan temporary files after interrupted ALTER +# cause InnoDB: Operating system error number 17 and eventual +# fatal error 71 +# +CREATE TABLE t1 (pk INT AUTO_INCREMENT PRIMARY KEY, i INT) ENGINE=InnoDB; +INSERT INTO t1 VALUES (NULL,1),(NULL,2),(NULL,3),(NULL,4),(NULL,5),(NULL,6),(NULL,7),(NULL,8); +INSERT INTO t1 SELECT NULL, i FROM t1; +INSERT INTO t1 SELECT NULL, i FROM t1; +INSERT INTO t1 SELECT NULL, i FROM t1; +INSERT INTO t1 SELECT NULL, i FROM t1; +INSERT INTO t1 SELECT NULL, i FROM t1; +LOCK TABLE t1 READ; +SET max_statement_time= 1; +ALTER TABLE t1 FORCE, ALGORITHM=COPY; +ERROR 70100: Query execution was interrupted (max_statement_time exceeded) +SET DEBUG_SYNC = 'now SIGNAL stop_waining'; +SET DEBUG_SYNC = 'now WAIT_FOR stop_waining'; +UNLOCK TABLES; +DROP TABLE t1; +SET DEBUG_SYNC = 'RESET'; diff --git a/mysql-test/suite/innodb/t/innodb-alter-debug.test b/mysql-test/suite/innodb/t/innodb-alter-debug.test index bc4b2ad8e56..d32faf39aad 100644 --- a/mysql-test/suite/innodb/t/innodb-alter-debug.test +++ b/mysql-test/suite/innodb/t/innodb-alter-debug.test @@ -100,3 +100,31 @@ DROP TABLE t1; # Wait till all disconnects are completed --source include/wait_until_count_sessions.inc + +--echo # +--echo # MDEV-17470 Orphan temporary files after interrupted ALTER +--echo # cause InnoDB: Operating system error number 17 and eventual +--echo # fatal error 71 +--echo # +CREATE TABLE t1 (pk INT AUTO_INCREMENT PRIMARY KEY, i INT) ENGINE=InnoDB; +INSERT INTO t1 VALUES (NULL,1),(NULL,2),(NULL,3),(NULL,4),(NULL,5),(NULL,6),(NULL,7),(NULL,8); +INSERT INTO t1 SELECT NULL, i FROM t1; +INSERT INTO t1 SELECT NULL, i FROM t1; +INSERT INTO t1 SELECT NULL, i FROM t1; +INSERT INTO t1 SELECT NULL, i FROM t1; +INSERT INTO t1 SELECT NULL, i FROM t1; + +LOCK TABLE t1 READ; + +--connect (con1,localhost,root,,test) +SET max_statement_time= 1; +--error ER_STATEMENT_TIMEOUT +ALTER TABLE t1 FORCE, ALGORITHM=COPY; +SET DEBUG_SYNC = 'now SIGNAL stop_waining'; +--disconnect con1 + +--connection default +SET DEBUG_SYNC = 'now WAIT_FOR stop_waining'; +UNLOCK TABLES; +DROP TABLE t1; +SET DEBUG_SYNC = 'RESET'; diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc index bb815de3138..6ec45c591eb 100644 --- a/storage/innobase/row/row0mysql.cc +++ b/storage/innobase/row/row0mysql.cc @@ -4224,9 +4224,10 @@ row_drop_table_for_mysql( calling btr_search_drop_page_hash_index() while we hold the InnoDB dictionary lock, we will drop any adaptive hash index entries upfront. */ + const bool is_temp = dict_table_is_temporary(table) + || strstr(tablename_minus_db, tmp_file_prefix); while (buf_LRU_drop_page_hash_for_tablespace(table)) { - if ((!dict_table_is_temporary(table) - && trx_is_interrupted(trx)) + if ((!is_temp && trx_is_interrupted(trx)) || srv_shutdown_state != SRV_SHUTDOWN_NONE) { err = DB_INTERRUPTED; goto funct_exit; diff --git a/storage/xtradb/row/row0mysql.cc b/storage/xtradb/row/row0mysql.cc index 88ebe24f3bb..a5381df1995 100644 --- a/storage/xtradb/row/row0mysql.cc +++ b/storage/xtradb/row/row0mysql.cc @@ -4234,9 +4234,10 @@ row_drop_table_for_mysql( calling btr_search_drop_page_hash_index() while we hold the InnoDB dictionary lock, we will drop any adaptive hash index entries upfront. */ + const bool is_temp = dict_table_is_temporary(table) + || strstr(tablename_minus_db, tmp_file_prefix); while (buf_LRU_drop_page_hash_for_tablespace(table)) { - if ((!dict_table_is_temporary(table) - && trx_is_interrupted(trx)) + if ((!is_temp && trx_is_interrupted(trx)) || srv_shutdown_state != SRV_SHUTDOWN_NONE) { err = DB_INTERRUPTED; goto funct_exit;