diff --git a/sql/sql_admin.cc b/sql/sql_admin.cc index efdb67d01c41..bfe4edb67c46 100644 --- a/sql/sql_admin.cc +++ b/sql/sql_admin.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights +/* Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify @@ -168,7 +168,7 @@ static int prepare_for_repair(THD *thd, TABLE_LIST *table_list, */ if (wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN)) goto end; - close_all_tables_for_name(thd, table_list->table->s, FALSE); + close_all_tables_for_name(thd, table_list->table->s, FALSE, NULL); table_list->table= 0; } /* diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 27dcbee7b8f0..e9ce652cdb10 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. 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 @@ -1096,7 +1096,7 @@ bool close_cached_tables(THD *thd, TABLE_LIST *tables, result= TRUE; goto err_with_reopen; } - close_all_tables_for_name(thd, table->s, FALSE); + close_all_tables_for_name(thd, table->s, FALSE, NULL); } } @@ -1367,13 +1367,16 @@ static void close_open_tables(THD *thd) In that case the documented behaviour is to implicitly remove the table from LOCK TABLES list. + @param[in] skip_table + TABLE instance that should be kept open. @pre Must be called with an X MDL lock on the table. */ void close_all_tables_for_name(THD *thd, TABLE_SHARE *share, - bool remove_from_locked_tables) + bool remove_from_locked_tables, + TABLE *skip_table) { char key[MAX_DBKEY_LENGTH]; uint key_length= share->table_cache_key.length; @@ -1388,7 +1391,8 @@ close_all_tables_for_name(THD *thd, TABLE_SHARE *share, TABLE *table= *prev; if (table->s->table_cache_key.length == key_length && - !memcmp(table->s->table_cache_key.str, key, key_length)) + !memcmp(table->s->table_cache_key.str, key, key_length) && + table != skip_table) { thd->locked_tables_list.unlink_from_list(thd, table->pos_in_locked_tables, @@ -1401,7 +1405,8 @@ close_all_tables_for_name(THD *thd, TABLE_SHARE *share, mysql_lock_remove(thd, thd->lock, table); /* Inform handler that table will be dropped after close */ - if (table->db_stat) /* Not true for partitioned tables. */ + if (table->db_stat && /* Not true for partitioned tables. */ + skip_table == NULL) table->file->extra(HA_EXTRA_PREPARE_FOR_DROP); close_thread_table(thd, prev); } @@ -1411,9 +1416,12 @@ close_all_tables_for_name(THD *thd, TABLE_SHARE *share, prev= &table->next; } } + + if (skip_table == NULL) { /* Remove the table share from the cache. */ tdc_remove_table(thd, TDC_RT_REMOVE_ALL, db, table_name, FALSE); + } } diff --git a/sql/sql_base.h b/sql/sql_base.h index b118c93ac289..28568acc0818 100644 --- a/sql/sql_base.h +++ b/sql/sql_base.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved. 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 @@ -306,7 +306,8 @@ bool close_cached_tables(THD *thd, TABLE_LIST *tables, bool wait_for_refresh, ulong timeout); bool close_cached_connection_tables(THD *thd, LEX_STRING *connect_string); void close_all_tables_for_name(THD *thd, TABLE_SHARE *share, - bool remove_from_locked_tables); + bool remove_from_locked_tables, + TABLE *skip_table); OPEN_TABLE_LIST *list_open_tables(THD *thd, const char *db, const char *wild); void tdc_remove_table(THD *thd, enum_tdc_remove_table_type remove_type, const char *db, const char *table_name, diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index 65d4da0f2f66..bd76a92dc68a 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved. 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 @@ -6512,7 +6512,7 @@ static void alter_partition_lock_handling(ALTER_PARTITION_PARAM_TYPE *lpt) THD *thd= lpt->thd; if (lpt->old_table) - close_all_tables_for_name(thd, lpt->old_table->s, FALSE); + close_all_tables_for_name(thd, lpt->old_table->s, FALSE, NULL); if (lpt->table) { /* @@ -6549,7 +6549,7 @@ static int alter_close_tables(ALTER_PARTITION_PARAM_TYPE *lpt, bool close_old) } if (close_old && lpt->old_table) { - close_all_tables_for_name(lpt->thd, lpt->old_table->s, FALSE); + close_all_tables_for_name(lpt->thd, lpt->old_table->s, FALSE, NULL); lpt->old_table= 0; } DBUG_RETURN(0); diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 58bcf5ca1d4c..6d02140cfcb6 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -1,5 +1,5 @@ /* - Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. 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 @@ -2165,7 +2165,7 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists, error= -1; goto err; } - close_all_tables_for_name(thd, table->table->s, TRUE); + close_all_tables_for_name(thd, table->table->s, TRUE, NULL); table->table= 0; } @@ -6168,7 +6168,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, */ if (wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN)) goto err; - close_all_tables_for_name(thd, table->s, TRUE); + close_all_tables_for_name(thd, table->s, TRUE, NULL); /* Then, we want check once again that target table does not exist. Actually the order of these two steps does not matter since @@ -6305,6 +6305,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, changes only" means also that the handler for the table does not change. The table is open and locked. The handler can be accessed. */ + if (need_copy_table == ALTER_TABLE_INDEX_CHANGED) { int pk_changed= 0; @@ -6606,6 +6607,19 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, thd->count_cuted_fields= CHECK_FIELD_WARN; // calc cuted fields thd->cuted_fields=0L; copied=deleted=0; + + if (thd->locked_tables_mode == LTM_LOCK_TABLES || + thd->locked_tables_mode == LTM_PRELOCKED_UNDER_LOCK_TABLES) + { + /* + Temporarily close the TABLE instances belonging to this + thread except the one to be used for ALTER TABLE. + + This is mostly needed to satisfy InnoDB assumptions/asserts. + */ + close_all_tables_for_name(thd, table->s, false, table); + } + /* We do not copy data for MERGE tables. Only the children have data. MERGE tables have HA_NO_COPY_ON_ALTER set. @@ -6877,7 +6891,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, } close_all_tables_for_name(thd, table->s, - new_name != table_name || new_db != db); + new_name != table_name || new_db != db, NULL); error=0; table_list->table= table= 0; /* Safety */ diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc index 0a4f549a052b..fe1131c41640 100644 --- a/sql/sql_trigger.cc +++ b/sql/sql_trigger.cc @@ -1,5 +1,5 @@ /* - Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2004, 2018, Oracle and/or its affiliates. All rights reserved. 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 @@ -568,7 +568,7 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create) if (result) goto end; - close_all_tables_for_name(thd, table->s, FALSE); + close_all_tables_for_name(thd, table->s, FALSE, NULL); /* Reopen the table if we were under LOCK TABLES. Ignore the return value for now. It's better to diff --git a/sql/sql_truncate.cc b/sql/sql_truncate.cc index 4f250e6e7a07..d8a0205a4958 100644 --- a/sql/sql_truncate.cc +++ b/sql/sql_truncate.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved. 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 @@ -394,7 +394,7 @@ bool Truncate_statement::lock_table(THD *thd, TABLE_LIST *table_ref, m_ticket_downgrade= table->mdl_ticket; /* Close if table is going to be recreated. */ if (*hton_can_recreate) - close_all_tables_for_name(thd, table->s, FALSE); + close_all_tables_for_name(thd, table->s, FALSE, NULL); } else {