From 22914ec793b850438c77acf070f8441cf307ebf6 Mon Sep 17 00:00:00 2001 From: Aleksey Midenkov Date: Tue, 5 Feb 2019 00:57:31 +0300 Subject: [PATCH] MDEV-18154 Deadlock and assertion upon no-op ALTER under LOCK TABLES 1. Fix DBUG_ASSERT(!table->pos_in_locked_tables) in tc_release_table(); 2. Fix access of prematurely freed MDL_ticket: don't close ticket if table was not closed; 3. Fix deadlock after erroneous ALTER. mysql_alter_table() leaves dirty table->m_needs_reopen in case of error exit which then incorrectly treated by mysql_lock_tables(). --- mysql-test/main/alter_table.result | 18 ++++++++++++++++++ mysql-test/main/alter_table.test | 18 ++++++++++++++++++ sql/sql_base.cc | 1 + sql/sql_table.cc | 6 +++++- 4 files changed, 42 insertions(+), 1 deletion(-) diff --git a/mysql-test/main/alter_table.result b/mysql-test/main/alter_table.result index 7a88f9165da..c5d974f4469 100644 --- a/mysql-test/main/alter_table.result +++ b/mysql-test/main/alter_table.result @@ -2539,3 +2539,21 @@ test.t1 analyze status OK set @@use_stat_tables= @save_use_stat_tables; set @@optimizer_use_condition_selectivity= @save_optimizer_use_condition_selectivity; drop table t1; +# +# MDEV-18154 Deadlock and assertion upon no-op ALTER under LOCK TABLES +# +create or replace table t1 (pk int, i int, primary key (pk)) engine myisam; +create or replace view v1 as select * from t1; +lock table v1 read, t1 write; +alter table t1 change f1 f2 int; +ERROR 42S22: Unknown column 'f1' in 't1' +set max_statement_time= 1; +alter table t1 add column if not exists i int after pk; +Warnings: +Note 1060 Duplicate column name 'i' +set max_statement_time= 0; +drop table t1; +drop view v1; +# +# End of 10.3 tests +# diff --git a/mysql-test/main/alter_table.test b/mysql-test/main/alter_table.test index 0fab5575f13..5c29dfae6b3 100644 --- a/mysql-test/main/alter_table.test +++ b/mysql-test/main/alter_table.test @@ -2057,3 +2057,21 @@ analyze table t1; set @@use_stat_tables= @save_use_stat_tables; set @@optimizer_use_condition_selectivity= @save_optimizer_use_condition_selectivity; drop table t1; + +--echo # +--echo # MDEV-18154 Deadlock and assertion upon no-op ALTER under LOCK TABLES +--echo # +create or replace table t1 (pk int, i int, primary key (pk)) engine myisam; +create or replace view v1 as select * from t1; +lock table v1 read, t1 write; +--error ER_BAD_FIELD_ERROR +alter table t1 change f1 f2 int; +set max_statement_time= 1; +alter table t1 add column if not exists i int after pk; +set max_statement_time= 0; +drop table t1; +drop view v1; + +--echo # +--echo # End of 10.3 tests +--echo # diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 287d5771155..99c8a227861 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -2433,6 +2433,7 @@ unlink_all_closed_tables(THD *thd, MYSQL_LOCK *lock, size_t reopen_count) DBUG_ASSERT(thd->open_tables == m_reopen_array[reopen_count]); thd->open_tables->pos_in_locked_tables->table= NULL; + thd->open_tables->pos_in_locked_tables= NULL; close_thread_table(thd, &thd->open_tables); } diff --git a/sql/sql_table.cc b/sql/sql_table.cc index a615dd9f1ed..eb623e14912 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -7837,6 +7837,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, Create_field *def; Field **f_ptr,*field; MY_BITMAP *dropped_fields= NULL; // if it's NULL - no dropped fields + bool save_reopen= table->m_needs_reopen; DBUG_ENTER("mysql_prepare_alter_table"); /* @@ -8516,7 +8517,9 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, alter_info->create_list.swap(new_create_list); alter_info->key_list.swap(new_key_list); alter_info->check_constraint_list.swap(new_constraint_list); + DBUG_RETURN(rc); err: + table->m_needs_reopen= save_reopen; DBUG_RETURN(rc); } @@ -10195,7 +10198,8 @@ err_with_mdl: tables and release the exclusive metadata lock. */ thd->locked_tables_list.unlink_all_closed_tables(thd, NULL, 0); - thd->mdl_context.release_all_locks_for_name(mdl_ticket); + if (!table_list->table) + thd->mdl_context.release_all_locks_for_name(mdl_ticket); DBUG_RETURN(true); }