mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
Split tdc_remove_table()
TDC_RT_REMOVE_ALL -> tdc_remove_table(). Some occurrences replaced with TDC_element::flush() (whenver TABLE_SHARE is available). TDC_RT_REMOVE_NOT_OWN[_KEEP_SHARE] -> TDC_element::flush(). These modes assume that current thread owns TABLE_SHARE reference, which means we can avoid hash lookup and flush unused TABLE instances directly. TDC_RT_REMOVE_UNUSED -> TDC_element::flush_unused(). Only [ab]used by mysql_admin_table() currently. Should be removed eventually. Part of MDEV-17882 - Cleanup refresh version
This commit is contained in:
@ -430,8 +430,7 @@ rpl_slave_state::truncate_state_table(THD *thd)
|
|||||||
MYSQL_OPEN_IGNORE_LOGGING_FORMAT)))
|
MYSQL_OPEN_IGNORE_LOGGING_FORMAT)))
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(!tlist.table->file->row_logging);
|
DBUG_ASSERT(!tlist.table->file->row_logging);
|
||||||
tdc_remove_table(thd, TDC_RT_REMOVE_NOT_OWN, "mysql",
|
tlist.table->s->tdc->flush(thd, true);
|
||||||
rpl_gtid_slave_state_table_name.str);
|
|
||||||
err= tlist.table->file->ha_truncate();
|
err= tlist.table->file->ha_truncate();
|
||||||
|
|
||||||
if (err)
|
if (err)
|
||||||
|
@ -1156,8 +1156,7 @@ send_result_message:
|
|||||||
}
|
}
|
||||||
else if (open_for_modify || fatal_error)
|
else if (open_for_modify || fatal_error)
|
||||||
{
|
{
|
||||||
tdc_remove_table(thd, TDC_RT_REMOVE_UNUSED,
|
table->table->s->tdc->flush_unused(true);
|
||||||
table->db.str, table->table_name.str);
|
|
||||||
/*
|
/*
|
||||||
May be something modified. Consequently, we have to
|
May be something modified. Consequently, we have to
|
||||||
invalidate the query cache.
|
invalidate the query cache.
|
||||||
|
@ -442,8 +442,7 @@ bool close_cached_tables(THD *thd, TABLE_LIST *tables,
|
|||||||
DBUG_RETURN(true);
|
DBUG_RETURN(true);
|
||||||
|
|
||||||
for (TABLE_LIST *table= tables; table; table= table->next_local)
|
for (TABLE_LIST *table= tables; table; table= table->next_local)
|
||||||
tdc_remove_table(thd, TDC_RT_REMOVE_ALL, table->db.str,
|
tdc_remove_table(thd, table->db.str, table->table_name.str);
|
||||||
table->table_name.str);
|
|
||||||
}
|
}
|
||||||
DBUG_RETURN(false);
|
DBUG_RETURN(false);
|
||||||
}
|
}
|
||||||
@ -1310,8 +1309,7 @@ bool wait_while_table_is_used(THD *thd, TABLE *table,
|
|||||||
thd->variables.lock_wait_timeout))
|
thd->variables.lock_wait_timeout))
|
||||||
DBUG_RETURN(TRUE);
|
DBUG_RETURN(TRUE);
|
||||||
|
|
||||||
tdc_remove_table(thd, TDC_RT_REMOVE_NOT_OWN,
|
table->s->tdc->flush(thd, true);
|
||||||
table->s->db.str, table->s->table_name.str);
|
|
||||||
/* extra() call must come only after all instances above are closed */
|
/* extra() call must come only after all instances above are closed */
|
||||||
if (function != HA_EXTRA_NOT_USED)
|
if (function != HA_EXTRA_NOT_USED)
|
||||||
(void) table->file->extra(function);
|
(void) table->file->extra(function);
|
||||||
@ -1350,9 +1348,8 @@ void drop_open_table(THD *thd, TABLE *table, const LEX_CSTRING *db_name,
|
|||||||
|
|
||||||
handlerton *table_type= table->s->db_type();
|
handlerton *table_type= table->s->db_type();
|
||||||
table->file->extra(HA_EXTRA_PREPARE_FOR_DROP);
|
table->file->extra(HA_EXTRA_PREPARE_FOR_DROP);
|
||||||
|
table->s->tdc->flush(thd, true);
|
||||||
close_thread_table(thd, &thd->open_tables);
|
close_thread_table(thd, &thd->open_tables);
|
||||||
/* Remove the table share from the table cache. */
|
|
||||||
tdc_remove_table(thd, TDC_RT_REMOVE_ALL, db_name->str, table_name->str);
|
|
||||||
/* Remove the table from the storage engine and rm the .frm. */
|
/* Remove the table from the storage engine and rm the .frm. */
|
||||||
quick_rm_table(thd, table_type, db_name, table_name, 0);
|
quick_rm_table(thd, table_type, db_name, table_name, 0);
|
||||||
}
|
}
|
||||||
@ -2947,8 +2944,7 @@ static bool auto_repair_table(THD *thd, TABLE_LIST *table_list)
|
|||||||
|
|
||||||
tdc_release_share(share);
|
tdc_release_share(share);
|
||||||
/* Remove the repaired share from the table cache. */
|
/* Remove the repaired share from the table cache. */
|
||||||
tdc_remove_table(thd, TDC_RT_REMOVE_ALL,
|
tdc_remove_table(thd, table_list->db.str, table_list->table_name.str);
|
||||||
table_list->db.str, table_list->table_name.str);
|
|
||||||
end_free:
|
end_free:
|
||||||
my_free(entry);
|
my_free(entry);
|
||||||
return result;
|
return result;
|
||||||
@ -3119,7 +3115,7 @@ Open_table_context::recover_from_failed_open()
|
|||||||
get_timeout(), 0)))
|
get_timeout(), 0)))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
tdc_remove_table(m_thd, TDC_RT_REMOVE_ALL, m_failed_table->db.str,
|
tdc_remove_table(m_thd, m_failed_table->db.str,
|
||||||
m_failed_table->table_name.str);
|
m_failed_table->table_name.str);
|
||||||
|
|
||||||
m_thd->get_stmt_da()->clear_warning_info(m_thd->query_id);
|
m_thd->get_stmt_da()->clear_warning_info(m_thd->query_id);
|
||||||
@ -3155,7 +3151,7 @@ Open_table_context::recover_from_failed_open()
|
|||||||
get_timeout(), 0)))
|
get_timeout(), 0)))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
tdc_remove_table(m_thd, TDC_RT_REMOVE_ALL, m_failed_table->db.str,
|
tdc_remove_table(m_thd, m_failed_table->db.str,
|
||||||
m_failed_table->table_name.str);
|
m_failed_table->table_name.str);
|
||||||
|
|
||||||
result= auto_repair_table(m_thd, m_failed_table);
|
result= auto_repair_table(m_thd, m_failed_table);
|
||||||
|
@ -825,8 +825,7 @@ bool Sql_cmd_alter_table_truncate_partition::execute(THD *thd)
|
|||||||
if (thd->mdl_context.upgrade_shared_lock(ticket, MDL_EXCLUSIVE, timeout))
|
if (thd->mdl_context.upgrade_shared_lock(ticket, MDL_EXCLUSIVE, timeout))
|
||||||
DBUG_RETURN(TRUE);
|
DBUG_RETURN(TRUE);
|
||||||
|
|
||||||
tdc_remove_table(thd, TDC_RT_REMOVE_NOT_OWN, first_table->db.str,
|
first_table->table->s->tdc->flush(thd, true);
|
||||||
first_table->table_name.str);
|
|
||||||
|
|
||||||
partition= (ha_partition*) first_table->table->file;
|
partition= (ha_partition*) first_table->table->file;
|
||||||
/* Invoke the handler method responsible for truncating the partition. */
|
/* Invoke the handler method responsible for truncating the partition. */
|
||||||
|
@ -309,8 +309,7 @@ do_rename(THD *thd, TABLE_LIST *ren_table, const LEX_CSTRING *new_db,
|
|||||||
Shared table. Just drop the old .frm as it's not correct anymore
|
Shared table. Just drop the old .frm as it's not correct anymore
|
||||||
Discovery will find the old table when it's accessed
|
Discovery will find the old table when it's accessed
|
||||||
*/
|
*/
|
||||||
tdc_remove_table(thd, TDC_RT_REMOVE_ALL,
|
tdc_remove_table(thd, ren_table->db.str, ren_table->table_name.str);
|
||||||
ren_table->db.str, ren_table->table_name.str);
|
|
||||||
quick_rm_table(thd, 0, &ren_table->db, &old_alias, FRM_ONLY, 0);
|
quick_rm_table(thd, 0, &ren_table->db, &old_alias, FRM_ONLY, 0);
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
@ -329,8 +328,7 @@ do_rename(THD *thd, TABLE_LIST *ren_table, const LEX_CSTRING *new_db,
|
|||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
tdc_remove_table(thd, TDC_RT_REMOVE_ALL,
|
tdc_remove_table(thd, ren_table->db.str, ren_table->table_name.str);
|
||||||
ren_table->db.str, ren_table->table_name.str);
|
|
||||||
|
|
||||||
if (hton != view_pseudo_hton)
|
if (hton != view_pseudo_hton)
|
||||||
{
|
{
|
||||||
|
@ -2485,8 +2485,7 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists,
|
|||||||
table->table= 0;
|
table->table= 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
tdc_remove_table(thd, TDC_RT_REMOVE_ALL, table->db.str,
|
tdc_remove_table(thd, table->db.str, table->table_name.str);
|
||||||
table->table_name.str);
|
|
||||||
|
|
||||||
/* Check that we have an exclusive lock on the table to be dropped. */
|
/* Check that we have an exclusive lock on the table to be dropped. */
|
||||||
DBUG_ASSERT(thd->mdl_context.is_lock_owner(MDL_key::TABLE, table->db.str,
|
DBUG_ASSERT(thd->mdl_context.is_lock_owner(MDL_key::TABLE, table->db.str,
|
||||||
@ -7753,8 +7752,7 @@ static bool mysql_inplace_alter_table(THD *thd,
|
|||||||
thd->variables.lock_wait_timeout))
|
thd->variables.lock_wait_timeout))
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
tdc_remove_table(thd, TDC_RT_REMOVE_NOT_OWN_KEEP_SHARE,
|
table->s->tdc->flush(thd, false);
|
||||||
table->s->db.str, table->s->table_name.str);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -375,8 +375,7 @@ bool Sql_cmd_truncate_table::lock_table(THD *thd, TABLE_LIST *table_ref,
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Table is already locked exclusively. Remove cached instances. */
|
/* Table is already locked exclusively. Remove cached instances. */
|
||||||
tdc_remove_table(thd, TDC_RT_REMOVE_ALL, table_ref->db.str,
|
tdc_remove_table(thd, table_ref->db.str, table_ref->table_name.str);
|
||||||
table_ref->table_name.str);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DBUG_RETURN(FALSE);
|
DBUG_RETURN(FALSE);
|
||||||
|
@ -655,8 +655,7 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views,
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
if (!res)
|
if (!res)
|
||||||
tdc_remove_table(thd, TDC_RT_REMOVE_ALL, view->db.str,
|
tdc_remove_table(thd, view->db.str, view->table_name.str);
|
||||||
view->table_name.str);
|
|
||||||
|
|
||||||
if (!res && mysql_bin_log.is_open())
|
if (!res && mysql_bin_log.is_open())
|
||||||
{
|
{
|
||||||
@ -1876,8 +1875,7 @@ bool mysql_drop_view(THD *thd, TABLE_LIST *views, enum_drop_mode drop_mode)
|
|||||||
For a view, there is a TABLE_SHARE object.
|
For a view, there is a TABLE_SHARE object.
|
||||||
Remove it from the table definition cache, in case the view was cached.
|
Remove it from the table definition cache, in case the view was cached.
|
||||||
*/
|
*/
|
||||||
tdc_remove_table(thd, TDC_RT_REMOVE_ALL, view->db.str,
|
tdc_remove_table(thd, view->db.str, view->table_name.str);
|
||||||
view->table_name.str);
|
|
||||||
query_cache_invalidate3(thd, view, 0);
|
query_cache_invalidate3(thd, view, 0);
|
||||||
sp_cache_invalidate();
|
sp_cache_invalidate();
|
||||||
}
|
}
|
||||||
|
@ -997,36 +997,9 @@ void tdc_release_share(TABLE_SHARE *share)
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Remove all or some (depending on parameter) instances of TABLE and
|
Removes all TABLE instances and corresponding TABLE_SHARE
|
||||||
TABLE_SHARE from the table definition cache.
|
|
||||||
|
|
||||||
@param thd Thread context
|
@param thd Thread context
|
||||||
@param remove_type Type of removal:
|
|
||||||
TDC_RT_REMOVE_ALL - remove all TABLE instances and
|
|
||||||
TABLE_SHARE instance. There
|
|
||||||
should be no used TABLE objects
|
|
||||||
and caller should have exclusive
|
|
||||||
metadata lock on the table.
|
|
||||||
TDC_RT_REMOVE_NOT_OWN - remove all TABLE instances
|
|
||||||
except those that belong to
|
|
||||||
this thread. There should be
|
|
||||||
no TABLE objects used by other
|
|
||||||
threads and caller should have
|
|
||||||
exclusive metadata lock on the
|
|
||||||
table.
|
|
||||||
TDC_RT_REMOVE_UNUSED - remove all unused TABLE
|
|
||||||
instances (if there are no
|
|
||||||
used instances will also
|
|
||||||
remove TABLE_SHARE).
|
|
||||||
TDC_RT_REMOVE_NOT_OWN_KEEP_SHARE -
|
|
||||||
remove all TABLE instances
|
|
||||||
except those that belong to
|
|
||||||
this thread, but don't mark
|
|
||||||
TABLE_SHARE as old. There
|
|
||||||
should be no TABLE objects
|
|
||||||
used by other threads and
|
|
||||||
caller should have exclusive
|
|
||||||
metadata lock on the table.
|
|
||||||
@param db Name of database
|
@param db Name of database
|
||||||
@param table_name Name of table
|
@param table_name Name of table
|
||||||
|
|
||||||
@ -1034,27 +1007,21 @@ void tdc_release_share(TABLE_SHARE *share)
|
|||||||
(other) thread (this should be achieved by using meta-data locks).
|
(other) thread (this should be achieved by using meta-data locks).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool tdc_remove_table(THD *thd, enum_tdc_remove_table_type remove_type,
|
void tdc_remove_table(THD *thd, const char *db, const char *table_name)
|
||||||
const char *db, const char *table_name)
|
|
||||||
{
|
{
|
||||||
Share_free_tables::List purge_tables;
|
Share_free_tables::List purge_tables;
|
||||||
TABLE *table;
|
|
||||||
TDC_element *element;
|
TDC_element *element;
|
||||||
uint my_refs= 1;
|
|
||||||
bool res= false;
|
|
||||||
DBUG_ENTER("tdc_remove_table");
|
DBUG_ENTER("tdc_remove_table");
|
||||||
DBUG_PRINT("enter",("name: %s remove_type: %d", table_name, remove_type));
|
DBUG_PRINT("enter", ("name: %s", table_name));
|
||||||
|
|
||||||
DBUG_ASSERT(remove_type == TDC_RT_REMOVE_UNUSED ||
|
DBUG_ASSERT(thd->mdl_context.is_lock_owner(MDL_key::TABLE, db, table_name,
|
||||||
thd->mdl_context.is_lock_owner(MDL_key::TABLE, db, table_name,
|
|
||||||
MDL_EXCLUSIVE));
|
MDL_EXCLUSIVE));
|
||||||
|
|
||||||
mysql_mutex_lock(&LOCK_unused_shares);
|
mysql_mutex_lock(&LOCK_unused_shares);
|
||||||
if (!(element= tdc_lock_share(thd, db, table_name)))
|
if (!(element= tdc_lock_share(thd, db, table_name)))
|
||||||
{
|
{
|
||||||
mysql_mutex_unlock(&LOCK_unused_shares);
|
mysql_mutex_unlock(&LOCK_unused_shares);
|
||||||
DBUG_ASSERT(remove_type != TDC_RT_REMOVE_NOT_OWN_KEEP_SHARE);
|
DBUG_VOID_RETURN;
|
||||||
DBUG_RETURN(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DBUG_ASSERT(element != MY_ERRPTR); // What can we do about it?
|
DBUG_ASSERT(element != MY_ERRPTR); // What can we do about it?
|
||||||
@ -1070,80 +1037,24 @@ bool tdc_remove_table(THD *thd, enum_tdc_remove_table_type remove_type,
|
|||||||
mysql_mutex_unlock(&LOCK_unused_shares);
|
mysql_mutex_unlock(&LOCK_unused_shares);
|
||||||
|
|
||||||
tdc_delete_share_from_hash(element);
|
tdc_delete_share_from_hash(element);
|
||||||
DBUG_RETURN(false);
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
mysql_mutex_unlock(&LOCK_unused_shares);
|
mysql_mutex_unlock(&LOCK_unused_shares);
|
||||||
|
|
||||||
element->ref_count++;
|
element->ref_count++;
|
||||||
if (remove_type != TDC_RT_REMOVE_NOT_OWN_KEEP_SHARE)
|
|
||||||
element->flushed= true;
|
|
||||||
|
|
||||||
tc_remove_all_unused_tables(element, &purge_tables);
|
tc_remove_all_unused_tables(element, &purge_tables);
|
||||||
|
|
||||||
if (remove_type == TDC_RT_REMOVE_NOT_OWN ||
|
|
||||||
remove_type == TDC_RT_REMOVE_NOT_OWN_KEEP_SHARE)
|
|
||||||
{
|
|
||||||
All_share_tables_list::Iterator it(element->all_tables);
|
|
||||||
while ((table= it++))
|
|
||||||
{
|
|
||||||
if (table->in_use == thd)
|
|
||||||
my_refs++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mysql_mutex_unlock(&element->LOCK_table_share);
|
mysql_mutex_unlock(&element->LOCK_table_share);
|
||||||
|
|
||||||
while ((table= purge_tables.pop_front()))
|
while (auto table= purge_tables.pop_front())
|
||||||
intern_close_table(table);
|
intern_close_table(table);
|
||||||
|
|
||||||
if (remove_type != TDC_RT_REMOVE_UNUSED)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
Even though current thread holds exclusive metadata lock on this share
|
|
||||||
(asserted above), concurrent FLUSH TABLES threads may be in process of
|
|
||||||
closing unused table instances belonging to this share. E.g.:
|
|
||||||
thr1 (FLUSH TABLES): table= share->tdc.free_tables.pop_front();
|
|
||||||
thr1 (FLUSH TABLES): share->tdc.all_tables.remove(table);
|
|
||||||
thr2 (ALTER TABLE): tdc_remove_table();
|
|
||||||
thr1 (FLUSH TABLES): intern_close_table(table);
|
|
||||||
|
|
||||||
Current remove type assumes that all table instances (except for those
|
|
||||||
that are owned by current thread) must be closed before
|
|
||||||
thd_remove_table() returns. Wait for such tables now.
|
|
||||||
|
|
||||||
intern_close_table() decrements ref_count and signals COND_release. When
|
|
||||||
ref_count drops down to number of references owned by current thread
|
|
||||||
waiting is completed.
|
|
||||||
|
|
||||||
Unfortunately TABLE_SHARE::wait_for_old_version() cannot be used here
|
|
||||||
because it waits for all table instances, whereas we have to wait only
|
|
||||||
for those that are not owned by current thread.
|
|
||||||
*/
|
|
||||||
mysql_mutex_lock(&element->LOCK_table_share);
|
mysql_mutex_lock(&element->LOCK_table_share);
|
||||||
while (element->ref_count > my_refs)
|
element->wait_for_refs(1);
|
||||||
mysql_cond_wait(&element->COND_release, &element->LOCK_table_share);
|
DBUG_ASSERT(element->all_tables.is_empty());
|
||||||
DBUG_ASSERT(element->all_tables.is_empty() ||
|
element->ref_count--;
|
||||||
remove_type != TDC_RT_REMOVE_ALL);
|
tdc_delete_share_from_hash(element);
|
||||||
#ifndef DBUG_OFF
|
DBUG_VOID_RETURN;
|
||||||
if (remove_type == TDC_RT_REMOVE_NOT_OWN ||
|
|
||||||
remove_type == TDC_RT_REMOVE_NOT_OWN_KEEP_SHARE)
|
|
||||||
{
|
|
||||||
All_share_tables_list::Iterator it(element->all_tables);
|
|
||||||
while ((table= it++))
|
|
||||||
DBUG_ASSERT(table->in_use == thd);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
mysql_mutex_unlock(&element->LOCK_table_share);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mysql_mutex_lock(&element->LOCK_table_share);
|
|
||||||
res= element->ref_count > 1;
|
|
||||||
mysql_mutex_unlock(&element->LOCK_table_share);
|
|
||||||
}
|
|
||||||
|
|
||||||
tdc_release_share(element->share);
|
|
||||||
|
|
||||||
DBUG_RETURN(res);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1284,3 +1195,94 @@ int show_tc_active_instances(THD *thd, SHOW_VAR *var, char *buff,
|
|||||||
tc_active_instances.load(std::memory_order_relaxed);
|
tc_active_instances.load(std::memory_order_relaxed);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Waits until ref_count goes down to given number
|
||||||
|
|
||||||
|
@param my_refs Number of references owned by the caller
|
||||||
|
|
||||||
|
Caller must own at least one TABLE_SHARE reference.
|
||||||
|
|
||||||
|
Even though current thread holds exclusive metadata lock on this share,
|
||||||
|
concurrent FLUSH TABLES threads may be in process of closing unused table
|
||||||
|
instances belonging to this share. E.g.:
|
||||||
|
thr1 (FLUSH TABLES): table= share->tdc.free_tables.pop_front();
|
||||||
|
thr1 (FLUSH TABLES): share->tdc.all_tables.remove(table);
|
||||||
|
thr2 (ALTER TABLE): tdc_remove_table();
|
||||||
|
thr1 (FLUSH TABLES): intern_close_table(table);
|
||||||
|
|
||||||
|
Current remove type assumes that all table instances (except for those
|
||||||
|
that are owned by current thread) must be closed before
|
||||||
|
thd_remove_table() returns. Wait for such tables now.
|
||||||
|
|
||||||
|
intern_close_table() decrements ref_count and signals COND_release. When
|
||||||
|
ref_count drops down to number of references owned by current thread
|
||||||
|
waiting is completed.
|
||||||
|
|
||||||
|
Unfortunately TABLE_SHARE::wait_for_old_version() cannot be used here
|
||||||
|
because it waits for all table instances, whereas we have to wait only
|
||||||
|
for those that are not owned by current thread.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void TDC_element::wait_for_refs(uint my_refs)
|
||||||
|
{
|
||||||
|
while (ref_count > my_refs)
|
||||||
|
mysql_cond_wait(&COND_release, &LOCK_table_share);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Flushes unused TABLE instances
|
||||||
|
|
||||||
|
@param thd Thread context
|
||||||
|
@param mark_flushed Whether to destroy TABLE_SHARE when released
|
||||||
|
|
||||||
|
Caller is allowed to own used TABLE instances.
|
||||||
|
There must be no TABLE objects used by other threads and caller must own
|
||||||
|
exclusive metadata lock on the table.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void TDC_element::flush(THD *thd, bool mark_flushed)
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(thd->mdl_context.is_lock_owner(MDL_key::TABLE, share->db.str,
|
||||||
|
share->table_name.str,
|
||||||
|
MDL_EXCLUSIVE));
|
||||||
|
|
||||||
|
flush_unused(mark_flushed);
|
||||||
|
|
||||||
|
mysql_mutex_lock(&LOCK_table_share);
|
||||||
|
All_share_tables_list::Iterator it(all_tables);
|
||||||
|
uint my_refs= 0;
|
||||||
|
while (auto table= it++)
|
||||||
|
{
|
||||||
|
if (table->in_use == thd)
|
||||||
|
my_refs++;
|
||||||
|
}
|
||||||
|
wait_for_refs(my_refs);
|
||||||
|
#ifndef DBUG_OFF
|
||||||
|
it.rewind();
|
||||||
|
while (auto table= it++)
|
||||||
|
DBUG_ASSERT(table->in_use == thd);
|
||||||
|
#endif
|
||||||
|
mysql_mutex_unlock(&LOCK_table_share);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Flushes unused TABLE instances
|
||||||
|
*/
|
||||||
|
|
||||||
|
void TDC_element::flush_unused(bool mark_flushed)
|
||||||
|
{
|
||||||
|
Share_free_tables::List purge_tables;
|
||||||
|
|
||||||
|
mysql_mutex_lock(&LOCK_table_share);
|
||||||
|
if (mark_flushed)
|
||||||
|
flushed= true;
|
||||||
|
tc_remove_all_unused_tables(this, &purge_tables);
|
||||||
|
mysql_mutex_unlock(&LOCK_table_share);
|
||||||
|
|
||||||
|
while (auto table= purge_tables.pop_front())
|
||||||
|
intern_close_table(table);
|
||||||
|
}
|
||||||
|
@ -54,17 +54,13 @@ struct TDC_element
|
|||||||
/** Avoid false sharing between TDC_element and free_tables */
|
/** Avoid false sharing between TDC_element and free_tables */
|
||||||
char pad[CPU_LEVEL1_DCACHE_LINESIZE];
|
char pad[CPU_LEVEL1_DCACHE_LINESIZE];
|
||||||
Share_free_tables free_tables[1];
|
Share_free_tables free_tables[1];
|
||||||
|
|
||||||
|
inline void wait_for_refs(uint my_refs);
|
||||||
|
void flush(THD *thd, bool mark_flushed);
|
||||||
|
void flush_unused(bool mark_flushed);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
enum enum_tdc_remove_table_type
|
|
||||||
{
|
|
||||||
TDC_RT_REMOVE_ALL,
|
|
||||||
TDC_RT_REMOVE_NOT_OWN,
|
|
||||||
TDC_RT_REMOVE_UNUSED,
|
|
||||||
TDC_RT_REMOVE_NOT_OWN_KEEP_SHARE
|
|
||||||
};
|
|
||||||
|
|
||||||
extern ulong tdc_size;
|
extern ulong tdc_size;
|
||||||
extern ulong tc_size;
|
extern ulong tc_size;
|
||||||
extern uint32 tc_instances;
|
extern uint32 tc_instances;
|
||||||
@ -81,8 +77,7 @@ int tdc_share_is_cached(THD *thd, const char *db, const char *table_name);
|
|||||||
extern TABLE_SHARE *tdc_acquire_share(THD *thd, TABLE_LIST *tl, uint flags,
|
extern TABLE_SHARE *tdc_acquire_share(THD *thd, TABLE_LIST *tl, uint flags,
|
||||||
TABLE **out_table= 0);
|
TABLE **out_table= 0);
|
||||||
extern void tdc_release_share(TABLE_SHARE *share);
|
extern void tdc_release_share(TABLE_SHARE *share);
|
||||||
extern bool tdc_remove_table(THD *thd, enum_tdc_remove_table_type remove_type,
|
void tdc_remove_table(THD *thd, const char *db, const char *table_name);
|
||||||
const char *db, const char *table_name);
|
|
||||||
|
|
||||||
extern int tdc_wait_for_old_version(THD *thd, const char *db,
|
extern int tdc_wait_for_old_version(THD *thd, const char *db,
|
||||||
const char *table_name,
|
const char *table_name,
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
#include "sql_priv.h"
|
#include "sql_priv.h"
|
||||||
#include "sql_plugin.h"
|
#include "sql_plugin.h"
|
||||||
#include "ha_heap.h"
|
#include "ha_heap.h"
|
||||||
#include "sql_base.h" // enum_tdc_remove_table_type
|
#include "sql_base.h"
|
||||||
|
|
||||||
static handler *heap_create_handler(handlerton *hton,
|
static handler *heap_create_handler(handlerton *hton,
|
||||||
TABLE_SHARE *table,
|
TABLE_SHARE *table,
|
||||||
|
@ -67,7 +67,7 @@ static int MDL_and_TDC(THD *thd,
|
|||||||
table);
|
table);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
tdc_remove_table(thd, TDC_RT_REMOVE_ALL, db, table);
|
tdc_remove_table(thd, db, table);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user