From 5900333aa5683bf0ef0698ccc911c6c07004ee3a Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 14 Jan 2015 12:10:13 +0100 Subject: [PATCH] MDEV-7404 REPAIR multiple tables crash in MDL_ticket::has_stronger_or_equal_type mysql_alter_table() that is used in mysql_recreate_table() doesn't expect many tables in the TABLE_LIST. --- .../suite/innodb/r/multi_repair-7404.result | 21 +++++++++++++++++++ .../suite/innodb/t/multi_repair-7404.test | 18 ++++++++++++++++ sql/sql_table.cc | 14 ++++++++----- 3 files changed, 48 insertions(+), 5 deletions(-) create mode 100644 mysql-test/suite/innodb/r/multi_repair-7404.result create mode 100644 mysql-test/suite/innodb/t/multi_repair-7404.test diff --git a/mysql-test/suite/innodb/r/multi_repair-7404.result b/mysql-test/suite/innodb/r/multi_repair-7404.result new file mode 100644 index 00000000000..b3db5755b87 --- /dev/null +++ b/mysql-test/suite/innodb/r/multi_repair-7404.result @@ -0,0 +1,21 @@ +create table `t1`(`a` int) engine=innodb partition by key (`a`); +create table `t2`(`b` int) engine=innodb; +create table `t3`(`c` int) engine=innodb; +insert t1 values (1); +insert t2 values (2); +insert t3 values (3); +repair table `t1`,`t2`,`t3`; +Table Op Msg_type Msg_text +test.t1 repair status OK +test.t2 repair status OK +test.t3 repair status OK +select * from t1; +a +1 +select * from t2; +b +2 +select * from t3; +c +3 +drop table t1, t2, t3; diff --git a/mysql-test/suite/innodb/t/multi_repair-7404.test b/mysql-test/suite/innodb/t/multi_repair-7404.test new file mode 100644 index 00000000000..0775cd8b200 --- /dev/null +++ b/mysql-test/suite/innodb/t/multi_repair-7404.test @@ -0,0 +1,18 @@ +# +# MDEV-7404 REPAIR multiple tables crash in MDL_ticket::has_stronger_or_equal_type +# + +--source include/have_partition.inc +--source include/have_innodb.inc +create table `t1`(`a` int) engine=innodb partition by key (`a`); +create table `t2`(`b` int) engine=innodb; +create table `t3`(`c` int) engine=innodb; +insert t1 values (1); +insert t2 values (2); +insert t3 values (3); +repair table `t1`,`t2`,`t3`; +select * from t1; +select * from t2; +select * from t3; +drop table t1, t2, t3; + diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 77dbc765809..477ecf4a350 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -7644,12 +7644,12 @@ err: /* - Recreates tables by calling mysql_alter_table(). + Recreates one table by calling mysql_alter_table(). SYNOPSIS mysql_recreate_table() thd Thread handler - tables Tables to recreate + table_list Table to recreate RETURN Like mysql_alter_table(). @@ -7658,9 +7658,9 @@ bool mysql_recreate_table(THD *thd, TABLE_LIST *table_list) { HA_CREATE_INFO create_info; Alter_info alter_info; + TABLE_LIST *next_table= table_list->next_global; DBUG_ENTER("mysql_recreate_table"); - DBUG_ASSERT(!table_list->next_global); /* table_list->table has been closed and freed. Do not reference uninitialized data. open_tables() could fail. @@ -7672,15 +7672,19 @@ bool mysql_recreate_table(THD *thd, TABLE_LIST *table_list) table_list->lock_type= TL_READ_NO_INSERT; /* Same applies to MDL request. */ table_list->mdl_request.set_type(MDL_SHARED_NO_WRITE); + /* hide following tables from open_tables() */ + table_list->next_global= NULL; bzero((char*) &create_info, sizeof(create_info)); create_info.row_type=ROW_TYPE_NOT_USED; create_info.default_table_charset=default_charset_info; /* Force alter table to recreate table */ alter_info.flags= (ALTER_CHANGE_COLUMN | ALTER_RECREATE); - DBUG_RETURN(mysql_alter_table(thd, NullS, NullS, &create_info, + bool res= mysql_alter_table(thd, NullS, NullS, &create_info, table_list, &alter_info, 0, - (ORDER *) 0, 0, 0)); + (ORDER *) 0, 0, 0); + table_list->next_global= next_table; + DBUG_RETURN(res); }