From 7953594a4d2682ed542313e2c27d8f279920c60f Mon Sep 17 00:00:00 2001 From: "ingo@mysql.com" <> Date: Tue, 13 Sep 2005 14:36:43 +0200 Subject: [PATCH] Bug#12845 - Stress test: Server crashes on CREATE .. SELECT statement Solution for 5.0. Changed calls to open_table(). Requested to ignore flush at places where the command did already lock tables. This could happen in CREATE ... SELECT and ALTER TABLE. No test case. The bug can only be triggered by true concurrency. The stress test suite provides a test case for this. --- sql/sql_base.cc | 28 +++++++++++++++------------- sql/sql_table.cc | 6 ++++-- 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 766840e667c..ea5ebede9c8 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -1030,23 +1030,23 @@ TABLE *reopen_name_locked_table(THD* thd, TABLE_LIST* table_list) SYNOPSIS open_table() - thd Thread context - table_list Open first table in list - refresh Pointer to memory that will be set to 1 if - we need to close all tables and reopen them - If this is a NULL pointer, then the is no version - number checking and the table is not put in the - thread-open-list - flags Bitmap of flags to modify how open works: - MYSQL_LOCK_IGNORE_FLUSH - Open table even if someone - has done a flush or namelock on it. + thd Thread context. + table_list Open first table in list. + refresh INOUT Pointer to memory that will be set to 1 if + we need to close all tables and reopen them. + If this is a NULL pointer, then the table is not + put in the thread-open-list. + flags Bitmap of flags to modify how open works: + MYSQL_LOCK_IGNORE_FLUSH - Open table even if + someone has done a flush or namelock on it. + No version number checking is done. IMPLEMENTATION Uses a cache of open tables to find a table not in use. RETURN NULL Open failed. If refresh is set then one should close - all other tables and retry the open + all other tables and retry the open. # Success. Pointer to TABLE object for open table. */ @@ -1201,10 +1201,12 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, if (!thd->open_tables) thd->version=refresh_version; - else if (thd->version != refresh_version && refresh) + else if ((thd->version != refresh_version) && + ! (flags & MYSQL_LOCK_IGNORE_FLUSH)) { /* Someone did a refresh while thread was opening tables */ - *refresh=1; + if (refresh) + *refresh=1; VOID(pthread_mutex_unlock(&LOCK_open)); DBUG_RETURN(0); } diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 611ab0f16aa..16926200c4c 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -1756,7 +1756,8 @@ TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info, create_info, *extra_fields, *keys, 0, select_field_count)) { - if (!(table= open_table(thd, create_table, thd->mem_root, (bool*)0, 0))) + if (! (table= open_table(thd, create_table, thd->mem_root, (bool*) 0, + MYSQL_LOCK_IGNORE_FLUSH))) quick_rm_table(create_info->db_type, create_table->db, table_case_name(create_info, create_table->table_name)); } @@ -3579,7 +3580,8 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, bzero((void*) &tbl, sizeof(tbl)); tbl.db= new_db; tbl.table_name= tbl.alias= tmp_name; - new_table= open_table(thd, &tbl, thd->mem_root, 0, 0); + new_table= open_table(thd, &tbl, thd->mem_root, (bool*) 0, + MYSQL_LOCK_IGNORE_FLUSH); } else {