summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksey Midenkov <midenok@gmail.com>2019-02-05 00:57:31 +0300
committerAleksey Midenkov <midenok@gmail.com>2019-08-11 12:32:08 +0300
commit22914ec793b850438c77acf070f8441cf307ebf6 (patch)
tree09976886fe80cdfe0eaf384916610c715a39c802
parent0b74c8832d45340a455f27c3b4aa20db5d8313db (diff)
downloadmariadb-git-22914ec793b850438c77acf070f8441cf307ebf6.tar.gz
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().
-rw-r--r--mysql-test/main/alter_table.result18
-rw-r--r--mysql-test/main/alter_table.test18
-rw-r--r--sql/sql_base.cc1
-rw-r--r--sql/sql_table.cc6
4 files changed, 42 insertions, 1 deletions
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);
}