From 474e5ecd1f4e39e57f7677e5d9dc2bd44da4768f Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Tue, 9 Apr 2013 15:34:49 +0200 Subject: [PATCH] Don't hold LOCK_open over open_table_def/open_binary_frm call --- sql/sql_base.cc | 28 ++++++++++++++++++++++------ sql/table.cc | 5 +++-- 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/sql/sql_base.cc b/sql/sql_base.cc index f58e121a511..cbcd8045348 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -597,6 +597,7 @@ TABLE_SHARE *get_table_share(THD *thd, TABLE_LIST *table_list, char *key, enum open_frm_error *error, my_hash_value_type hash_value) { + bool open_failed; TABLE_SHARE *share; DBUG_ENTER("get_table_share"); @@ -641,19 +642,33 @@ TABLE_SHARE *get_table_share(THD *thd, TABLE_LIST *table_list, char *key, free_table_share(share); goto err; } - if (open_table_def(thd, share, op)) + share->ref_count++; // Mark in use + share->error= OPEN_FRM_OPEN_ERROR; + mysql_mutex_lock(&share->LOCK_ha_data); + mysql_mutex_unlock(&LOCK_open); + + open_failed= open_table_def(thd, share, op); + + mysql_mutex_unlock(&share->LOCK_ha_data); + mysql_mutex_lock(&LOCK_open); + + if (open_failed) { *error= share->error; + share->ref_count--; (void) my_hash_delete(&table_def_cache, (uchar*) share); goto err; } - share->ref_count++; // Mark in use DBUG_PRINT("exit", ("share: 0x%lx ref_count: %u", (ulong) share, share->ref_count)); goto end; } + /* make sure that open_table_def() for this share is not running */ + mysql_mutex_lock(&share->LOCK_ha_data); + mysql_mutex_unlock(&share->LOCK_ha_data); + /* We found an existing table definition. Return it if we didn't get an error when reading the table definition from file. @@ -863,8 +878,9 @@ TABLE_SHARE *get_cached_table_share(const char *db, const char *table_name) mysql_mutex_assert_owner(&LOCK_open); key_length= create_table_def_key(key, db, table_name); - return (TABLE_SHARE*) my_hash_search(&table_def_cache, - (uchar*) key, key_length); + TABLE_SHARE* share= (TABLE_SHARE*)my_hash_search(&table_def_cache, + (uchar*) key, key_length); + return !share || share->error ? 0 : share; } @@ -2954,12 +2970,12 @@ bool open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, global read lock until end of this statement in order to have this statement blocked by active FLUSH TABLES WITH READ LOCK. - We don't block acquire this protection under LOCK TABLES as + We don't need to acquire this protection under LOCK TABLES as such protection already acquired at LOCK TABLES time and not released until UNLOCK TABLES. We don't block statements which modify only temporary tables - as these tables are not preserved by backup by any form of + as these tables are not preserved by any form of backup which uses FLUSH TABLES WITH READ LOCK. TODO: The fact that we sometimes acquire protection against diff --git a/sql/table.cc b/sql/table.cc index 661d448b743..6c6dea48bfd 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -751,15 +751,16 @@ enum open_frm_error open_table_def(THD *thd, TABLE_SHARE *share, if (!error) thd->status_var.opened_shares++; - DBUG_RETURN(error); + goto err_not_open; err: mysql_file_close(file, MYF(MY_WME)); err_not_open: + share->error= error; + if (error && !error_given) { - share->error= error; share->open_errno= my_errno; open_table_error(share, error, share->open_errno); }