summaryrefslogtreecommitdiff
path: root/sql/sql_base.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/sql_base.cc')
-rw-r--r--sql/sql_base.cc104
1 files changed, 46 insertions, 58 deletions
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index c227fd12f5b..78862985e97 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -1589,10 +1589,18 @@ bool close_thread_table(THD *thd, TABLE **table_ptr)
*table_ptr=table->next;
mysql_mutex_unlock(&thd->LOCK_thd_data);
+ if (! table->needs_reopen())
+ {
+ /* Avoid having MERGE tables with attached children in unused_tables. */
+ table->file->extra(HA_EXTRA_DETACH_CHILDREN);
+ /* Free memory and reset for next loop. */
+ free_field_buffers_larger_than(table, MAX_TDC_BLOB_SIZE);
+ table->file->ha_reset();
+ }
+
mysql_mutex_lock(&LOCK_open);
- if (table->s->needs_reopen() ||
- thd->version != refresh_version || table->needs_reopen() ||
+ if (table->s->needs_reopen() || table->needs_reopen() ||
table_def_shutdown_in_progress)
{
free_cache_entry(table);
@@ -1600,14 +1608,7 @@ bool close_thread_table(THD *thd, TABLE **table_ptr)
}
else
{
- /* Avoid to have MERGE tables with attached children in unused_tables. */
DBUG_ASSERT(table->file);
- table->file->extra(HA_EXTRA_DETACH_CHILDREN);
-
- /* Free memory and reset for next loop */
- free_field_buffers_larger_than(table,MAX_TDC_BLOB_SIZE);
-
- table->file->ha_reset();
table_def_unuse_table(table);
/*
We free the least used table, not the subject table,
@@ -2305,7 +2306,7 @@ void wait_for_condition(THD *thd, mysql_mutex_t *mutex, mysql_cond_t *cond)
@param[out] exists Out parameter which is set to TRUE if table
exists and to FALSE otherwise.
- @note This function assumes that caller owns LOCK_open mutex.
+ @note This function acquires LOCK_open internally.
It also assumes that the fact that there are no exclusive
metadata locks on the table was checked beforehand.
@@ -2313,28 +2314,30 @@ void wait_for_condition(THD *thd, mysql_mutex_t *mutex, mysql_cond_t *cond)
of engines (e.g. it was created on another node of NDB cluster)
this function will fetch and create proper .FRM file for it.
- @retval TRUE Some error occured
+ @retval TRUE Some error occurred
@retval FALSE No error. 'exists' out parameter set accordingly.
*/
bool check_if_table_exists(THD *thd, TABLE_LIST *table, bool *exists)
{
char path[FN_REFLEN + 1];
- int rc;
+ int rc= 0;
DBUG_ENTER("check_if_table_exists");
- mysql_mutex_assert_owner(&LOCK_open);
+ mysql_mutex_assert_not_owner(&LOCK_open);
*exists= TRUE;
+ mysql_mutex_lock(&LOCK_open);
+
if (get_cached_table_share(table->db, table->table_name))
- DBUG_RETURN(FALSE);
+ goto end;
build_table_filename(path, sizeof(path) - 1, table->db, table->table_name,
reg_ext, 0);
if (!access(path, F_OK))
- DBUG_RETURN(FALSE);
+ goto end;
/* .FRM file doesn't exist. Check if some engine can provide it. */
@@ -2344,19 +2347,17 @@ bool check_if_table_exists(THD *thd, TABLE_LIST *table, bool *exists)
{
/* Table does not exists in engines as well. */
*exists= FALSE;
- DBUG_RETURN(FALSE);
- }
- else if (!rc)
- {
- /* Table exists in some engine and .FRM for it was created. */
- DBUG_RETURN(FALSE);
+ rc= 0;
}
- else /* (rc > 0) */
+ else if (rc)
{
my_printf_error(ER_UNKNOWN_ERROR, "Failed to open '%-.64s', error while "
"unpacking from engine", MYF(0), table->table_name);
- DBUG_RETURN(TRUE);
}
+
+end:
+ mysql_mutex_unlock(&LOCK_open);
+ DBUG_RETURN(test(rc));
}
@@ -2651,7 +2652,7 @@ bool open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
if (thd->global_read_lock.wait_if_global_read_lock(thd, 1, 1))
DBUG_RETURN(TRUE);
- if (thd->version != refresh_version)
+ if (thd->open_tables && thd->open_tables->s->version != refresh_version)
{
(void) ot_ctx->request_backoff_action(Open_table_context::OT_WAIT_TDC,
NULL);
@@ -2848,48 +2849,24 @@ bool open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
}
hash_value= my_calc_hash(&table_def_cache, (uchar*) key, key_length);
- mysql_mutex_lock(&LOCK_open);
- /*
- If it's the first table from a list of tables used in a query,
- remember refresh_version (the version of open_cache state).
- If the version changes while we're opening the remaining tables,
- we will have to back off, close all the tables opened-so-far,
- and try to reopen them.
- Note: refresh_version is currently changed only during FLUSH TABLES.
- */
- if (!thd->open_tables)
- thd->version=refresh_version;
- else if ((thd->version != refresh_version) &&
- ! (flags & MYSQL_OPEN_IGNORE_FLUSH))
- {
- /* Someone did a refresh while thread was opening tables */
- mysql_mutex_unlock(&LOCK_open);
- (void) ot_ctx->request_backoff_action(Open_table_context::OT_WAIT_TDC,
- NULL);
- DBUG_RETURN(TRUE);
- }
if (table_list->open_strategy == TABLE_LIST::OPEN_IF_EXISTS)
{
bool exists;
if (check_if_table_exists(thd, table_list, &exists))
- goto err_unlock2;
+ DBUG_RETURN(TRUE);
if (!exists)
- {
- mysql_mutex_unlock(&LOCK_open);
DBUG_RETURN(FALSE);
- }
+
/* Table exists. Let us try to open it. */
}
else if (table_list->open_strategy == TABLE_LIST::OPEN_STUB)
- {
- mysql_mutex_unlock(&LOCK_open);
DBUG_RETURN(FALSE);
- }
+ mysql_mutex_lock(&LOCK_open);
#ifdef DISABLED_UNTIL_GRL_IS_MADE_PART_OF_MDL
if (!(share= (TABLE_SHARE *) mdl_ticket->get_cached_object()))
#endif
@@ -2911,7 +2888,7 @@ bool open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
my_error(ER_WRONG_MRG_TABLE, MYF(0));
goto err_unlock;
}
-
+
/*
This table is a view. Validate its metadata version: in particular,
that it was a view when the statement was prepared.
@@ -2980,7 +2957,15 @@ bool open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
}
#endif
- if (share->needs_reopen())
+
+ /*
+ If the version changes while we're opening the tables,
+ we have to back off, close all the tables opened-so-far,
+ and try to reopen them. Note: refresh_version is currently
+ changed only during FLUSH TABLES.
+ */
+ if (share->needs_reopen() ||
+ (thd->open_tables && thd->open_tables->s->version != share->version))
{
if (!(flags & MYSQL_OPEN_IGNORE_FLUSH))
{
@@ -3000,8 +2985,6 @@ bool open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
NULL);
DBUG_RETURN(TRUE);
}
- /* Force close at once after usage */
- thd->version= share->version;
}
if (!share->free_tables.is_empty())
@@ -3017,9 +3000,11 @@ bool open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
while (table_cache_count > table_cache_size && unused_tables)
free_cache_entry(unused_tables);
+ mysql_mutex_unlock(&LOCK_open);
+
/* make a new table */
if (!(table=(TABLE*) my_malloc(sizeof(*table),MYF(MY_WME))))
- goto err_unlock;
+ goto err_lock;
error= open_table_from_share(thd, share, alias,
(uint) (HA_OPEN_KEYFILE |
@@ -3041,16 +3026,17 @@ bool open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
(void) ot_ctx->request_backoff_action(Open_table_context::OT_REPAIR,
table_list);
- goto err_unlock;
+ goto err_lock;
}
if (open_table_entry_fini(thd, share, table))
{
closefrm(table, 0);
my_free((uchar*)table, MYF(0));
- goto err_unlock;
+ goto err_lock;
}
+ mysql_mutex_lock(&LOCK_open);
/* Add table to the share's used tables list. */
table_def_add_used_table(thd, table);
}
@@ -3112,6 +3098,8 @@ bool open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
table->file->extra(HA_EXTRA_DETACH_CHILDREN);
DBUG_RETURN(FALSE);
+err_lock:
+ mysql_mutex_lock(&LOCK_open);
err_unlock:
release_table_share(share);
err_unlock2: