MDEV-5864 - Reduce usage of LOCK_open: TABLE_SHARE::tdc.free_tables
Let TABLE_SHARE::tdc.free_tables, TABLE_SHARE::tdc.all_tables, TABLE_SHARE::tdc.flushed and corresponding invariants be protected by per-share TABLE_SHARE::tdc.LOCK_table_share instead of global LOCK_open.
This commit is contained in:
parent
8250824a12
commit
e4fde57712
@ -4,9 +4,9 @@ WHERE name LIKE 'wait/synch/mutex/%'
|
|||||||
OR name LIKE 'wait/synch/rwlock/%';
|
OR name LIKE 'wait/synch/rwlock/%';
|
||||||
flush status;
|
flush status;
|
||||||
select NAME from performance_schema.mutex_instances
|
select NAME from performance_schema.mutex_instances
|
||||||
where NAME = 'wait/synch/mutex/sql/LOCK_open';
|
where NAME = 'wait/synch/mutex/sql/TABLE_SHARE::tdc.LOCK_table_share' GROUP BY NAME;
|
||||||
NAME
|
NAME
|
||||||
wait/synch/mutex/sql/LOCK_open
|
wait/synch/mutex/sql/TABLE_SHARE::tdc.LOCK_table_share
|
||||||
select NAME from performance_schema.rwlock_instances
|
select NAME from performance_schema.rwlock_instances
|
||||||
where NAME = 'wait/synch/rwlock/sql/LOCK_grant';
|
where NAME = 'wait/synch/rwlock/sql/LOCK_grant';
|
||||||
NAME
|
NAME
|
||||||
@ -23,7 +23,7 @@ id b
|
|||||||
1 initial value
|
1 initial value
|
||||||
SET @before_count = (SELECT SUM(TIMER_WAIT)
|
SET @before_count = (SELECT SUM(TIMER_WAIT)
|
||||||
FROM performance_schema.events_waits_history_long
|
FROM performance_schema.events_waits_history_long
|
||||||
WHERE (EVENT_NAME = 'wait/synch/mutex/sql/LOCK_open'));
|
WHERE (EVENT_NAME = 'wait/synch/mutex/sql/TABLE_SHARE::tdc.LOCK_table_share'));
|
||||||
SELECT * FROM t1;
|
SELECT * FROM t1;
|
||||||
id b
|
id b
|
||||||
1 initial value
|
1 initial value
|
||||||
@ -36,12 +36,12 @@ id b
|
|||||||
8 initial value
|
8 initial value
|
||||||
SET @after_count = (SELECT SUM(TIMER_WAIT)
|
SET @after_count = (SELECT SUM(TIMER_WAIT)
|
||||||
FROM performance_schema.events_waits_history_long
|
FROM performance_schema.events_waits_history_long
|
||||||
WHERE (EVENT_NAME = 'wait/synch/mutex/sql/LOCK_open'));
|
WHERE (EVENT_NAME = 'wait/synch/mutex/sql/TABLE_SHARE::tdc.LOCK_table_share'));
|
||||||
SELECT IF((@after_count - @before_count) > 0, 'Success', 'Failure') test_fm1_timed;
|
SELECT IF((@after_count - @before_count) > 0, 'Success', 'Failure') test_fm1_timed;
|
||||||
test_fm1_timed
|
test_fm1_timed
|
||||||
Success
|
Success
|
||||||
UPDATE performance_schema.setup_instruments SET enabled = 'NO'
|
UPDATE performance_schema.setup_instruments SET enabled = 'NO'
|
||||||
WHERE NAME = 'wait/synch/mutex/sql/LOCK_open';
|
WHERE NAME = 'wait/synch/mutex/sql/TABLE_SHARE::tdc.LOCK_table_share';
|
||||||
TRUNCATE TABLE performance_schema.events_waits_history_long;
|
TRUNCATE TABLE performance_schema.events_waits_history_long;
|
||||||
TRUNCATE TABLE performance_schema.events_waits_history;
|
TRUNCATE TABLE performance_schema.events_waits_history;
|
||||||
TRUNCATE TABLE performance_schema.events_waits_current;
|
TRUNCATE TABLE performance_schema.events_waits_current;
|
||||||
@ -50,7 +50,7 @@ id b
|
|||||||
1 initial value
|
1 initial value
|
||||||
SET @before_count = (SELECT SUM(TIMER_WAIT)
|
SET @before_count = (SELECT SUM(TIMER_WAIT)
|
||||||
FROM performance_schema.events_waits_history_long
|
FROM performance_schema.events_waits_history_long
|
||||||
WHERE (EVENT_NAME = 'wait/synch/mutex/sql/LOCK_open'));
|
WHERE (EVENT_NAME = 'wait/synch/mutex/sql/TABLE_SHARE::tdc.LOCK_table_share'));
|
||||||
SELECT * FROM t1;
|
SELECT * FROM t1;
|
||||||
id b
|
id b
|
||||||
1 initial value
|
1 initial value
|
||||||
@ -63,7 +63,7 @@ id b
|
|||||||
8 initial value
|
8 initial value
|
||||||
SET @after_count = (SELECT SUM(TIMER_WAIT)
|
SET @after_count = (SELECT SUM(TIMER_WAIT)
|
||||||
FROM performance_schema.events_waits_history_long
|
FROM performance_schema.events_waits_history_long
|
||||||
WHERE (EVENT_NAME = 'wait/synch/mutex/sql/LOCK_open'));
|
WHERE (EVENT_NAME = 'wait/synch/mutex/sql/TABLE_SHARE::tdc.LOCK_table_share'));
|
||||||
SELECT IF((COALESCE(@after_count, 0) - COALESCE(@before_count, 0)) = 0, 'Success', 'Failure') test_fm2_timed;
|
SELECT IF((COALESCE(@after_count, 0) - COALESCE(@before_count, 0)) = 0, 'Success', 'Failure') test_fm2_timed;
|
||||||
test_fm2_timed
|
test_fm2_timed
|
||||||
Success
|
Success
|
||||||
|
@ -32,10 +32,6 @@ where name like "wait/synch/cond/mysys/THR_COND_threads";
|
|||||||
count(name)
|
count(name)
|
||||||
1
|
1
|
||||||
select count(name) from mutex_instances
|
select count(name) from mutex_instances
|
||||||
where name like "wait/synch/mutex/sql/LOCK_open";
|
|
||||||
count(name)
|
|
||||||
1
|
|
||||||
select count(name) from mutex_instances
|
|
||||||
where name like "wait/synch/mutex/sql/LOCK_thread_count";
|
where name like "wait/synch/mutex/sql/LOCK_thread_count";
|
||||||
count(name)
|
count(name)
|
||||||
1
|
1
|
||||||
|
@ -18,7 +18,7 @@ flush status;
|
|||||||
|
|
||||||
# Make sure objects are instrumented
|
# Make sure objects are instrumented
|
||||||
select NAME from performance_schema.mutex_instances
|
select NAME from performance_schema.mutex_instances
|
||||||
where NAME = 'wait/synch/mutex/sql/LOCK_open';
|
where NAME = 'wait/synch/mutex/sql/TABLE_SHARE::tdc.LOCK_table_share' GROUP BY NAME;
|
||||||
select NAME from performance_schema.rwlock_instances
|
select NAME from performance_schema.rwlock_instances
|
||||||
where NAME = 'wait/synch/rwlock/sql/LOCK_grant';
|
where NAME = 'wait/synch/rwlock/sql/LOCK_grant';
|
||||||
|
|
||||||
@ -48,18 +48,18 @@ SELECT * FROM t1 WHERE id = 1;
|
|||||||
|
|
||||||
SET @before_count = (SELECT SUM(TIMER_WAIT)
|
SET @before_count = (SELECT SUM(TIMER_WAIT)
|
||||||
FROM performance_schema.events_waits_history_long
|
FROM performance_schema.events_waits_history_long
|
||||||
WHERE (EVENT_NAME = 'wait/synch/mutex/sql/LOCK_open'));
|
WHERE (EVENT_NAME = 'wait/synch/mutex/sql/TABLE_SHARE::tdc.LOCK_table_share'));
|
||||||
|
|
||||||
SELECT * FROM t1;
|
SELECT * FROM t1;
|
||||||
|
|
||||||
SET @after_count = (SELECT SUM(TIMER_WAIT)
|
SET @after_count = (SELECT SUM(TIMER_WAIT)
|
||||||
FROM performance_schema.events_waits_history_long
|
FROM performance_schema.events_waits_history_long
|
||||||
WHERE (EVENT_NAME = 'wait/synch/mutex/sql/LOCK_open'));
|
WHERE (EVENT_NAME = 'wait/synch/mutex/sql/TABLE_SHARE::tdc.LOCK_table_share'));
|
||||||
|
|
||||||
SELECT IF((@after_count - @before_count) > 0, 'Success', 'Failure') test_fm1_timed;
|
SELECT IF((@after_count - @before_count) > 0, 'Success', 'Failure') test_fm1_timed;
|
||||||
|
|
||||||
UPDATE performance_schema.setup_instruments SET enabled = 'NO'
|
UPDATE performance_schema.setup_instruments SET enabled = 'NO'
|
||||||
WHERE NAME = 'wait/synch/mutex/sql/LOCK_open';
|
WHERE NAME = 'wait/synch/mutex/sql/TABLE_SHARE::tdc.LOCK_table_share';
|
||||||
|
|
||||||
TRUNCATE TABLE performance_schema.events_waits_history_long;
|
TRUNCATE TABLE performance_schema.events_waits_history_long;
|
||||||
TRUNCATE TABLE performance_schema.events_waits_history;
|
TRUNCATE TABLE performance_schema.events_waits_history;
|
||||||
@ -69,13 +69,13 @@ SELECT * FROM t1 WHERE id = 1;
|
|||||||
|
|
||||||
SET @before_count = (SELECT SUM(TIMER_WAIT)
|
SET @before_count = (SELECT SUM(TIMER_WAIT)
|
||||||
FROM performance_schema.events_waits_history_long
|
FROM performance_schema.events_waits_history_long
|
||||||
WHERE (EVENT_NAME = 'wait/synch/mutex/sql/LOCK_open'));
|
WHERE (EVENT_NAME = 'wait/synch/mutex/sql/TABLE_SHARE::tdc.LOCK_table_share'));
|
||||||
|
|
||||||
SELECT * FROM t1;
|
SELECT * FROM t1;
|
||||||
|
|
||||||
SET @after_count = (SELECT SUM(TIMER_WAIT)
|
SET @after_count = (SELECT SUM(TIMER_WAIT)
|
||||||
FROM performance_schema.events_waits_history_long
|
FROM performance_schema.events_waits_history_long
|
||||||
WHERE (EVENT_NAME = 'wait/synch/mutex/sql/LOCK_open'));
|
WHERE (EVENT_NAME = 'wait/synch/mutex/sql/TABLE_SHARE::tdc.LOCK_table_share'));
|
||||||
|
|
||||||
SELECT IF((COALESCE(@after_count, 0) - COALESCE(@before_count, 0)) = 0, 'Success', 'Failure') test_fm2_timed;
|
SELECT IF((COALESCE(@after_count, 0) - COALESCE(@before_count, 0)) = 0, 'Success', 'Failure') test_fm2_timed;
|
||||||
|
|
||||||
|
@ -43,9 +43,6 @@ select count(name) from cond_instances
|
|||||||
|
|
||||||
# Verify that these global mutexes have been properly initilized in sql
|
# Verify that these global mutexes have been properly initilized in sql
|
||||||
|
|
||||||
select count(name) from mutex_instances
|
|
||||||
where name like "wait/synch/mutex/sql/LOCK_open";
|
|
||||||
|
|
||||||
select count(name) from mutex_instances
|
select count(name) from mutex_instances
|
||||||
where name like "wait/synch/mutex/sql/LOCK_thread_count";
|
where name like "wait/synch/mutex/sql/LOCK_thread_count";
|
||||||
|
|
||||||
|
@ -790,7 +790,6 @@ MYSQL_LOCK *get_lock_data(THD *thd, TABLE **table_ptr, uint count, uint flags)
|
|||||||
@param thd Thread handle.
|
@param thd Thread handle.
|
||||||
@param db The database name.
|
@param db The database name.
|
||||||
|
|
||||||
This function cannot be called while holding LOCK_open mutex.
|
|
||||||
To avoid deadlocks, we do not try to obtain exclusive metadata
|
To avoid deadlocks, we do not try to obtain exclusive metadata
|
||||||
locks in LOCK TABLES mode, since in this mode there may be
|
locks in LOCK TABLES mode, since in this mode there may be
|
||||||
other metadata locks already taken by the current connection,
|
other metadata locks already taken by the current connection,
|
||||||
@ -842,9 +841,7 @@ bool lock_schema_name(THD *thd, const char *db)
|
|||||||
@param name Object name in the schema.
|
@param name Object name in the schema.
|
||||||
|
|
||||||
This function assumes that no metadata locks were acquired
|
This function assumes that no metadata locks were acquired
|
||||||
before calling it. Additionally, it cannot be called while
|
before calling it. It is enforced by asserts in MDL_context::acquire_locks().
|
||||||
holding LOCK_open mutex. Both these invariants are enforced by
|
|
||||||
asserts in MDL_context::acquire_locks().
|
|
||||||
To avoid deadlocks, we do not try to obtain exclusive metadata
|
To avoid deadlocks, we do not try to obtain exclusive metadata
|
||||||
locks in LOCK TABLES mode, since in this mode there may be
|
locks in LOCK TABLES mode, since in this mode there may be
|
||||||
other metadata locks already taken by the current connection,
|
other metadata locks already taken by the current connection,
|
||||||
|
@ -1903,8 +1903,6 @@ bool MDL_lock::has_pending_conflicting_lock(enum_mdl_type type)
|
|||||||
{
|
{
|
||||||
bool result;
|
bool result;
|
||||||
|
|
||||||
mysql_mutex_assert_not_owner(&LOCK_open);
|
|
||||||
|
|
||||||
mysql_prlock_rdlock(&m_rwlock);
|
mysql_prlock_rdlock(&m_rwlock);
|
||||||
result= (m_waiting.bitmap() & incompatible_granted_types_bitmap()[type]);
|
result= (m_waiting.bitmap() & incompatible_granted_types_bitmap()[type]);
|
||||||
mysql_prlock_unlock(&m_rwlock);
|
mysql_prlock_unlock(&m_rwlock);
|
||||||
@ -2079,7 +2077,6 @@ MDL_context::try_acquire_lock_impl(MDL_request *mdl_request,
|
|||||||
|
|
||||||
/* Don't take chances in production. */
|
/* Don't take chances in production. */
|
||||||
mdl_request->ticket= NULL;
|
mdl_request->ticket= NULL;
|
||||||
mysql_mutex_assert_not_owner(&LOCK_open);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Check whether the context already holds a shared lock on the object,
|
Check whether the context already holds a shared lock on the object,
|
||||||
@ -2169,7 +2166,6 @@ MDL_context::clone_ticket(MDL_request *mdl_request)
|
|||||||
{
|
{
|
||||||
MDL_ticket *ticket;
|
MDL_ticket *ticket;
|
||||||
|
|
||||||
mysql_mutex_assert_not_owner(&LOCK_open);
|
|
||||||
/*
|
/*
|
||||||
By submitting mdl_request->type to MDL_ticket::create()
|
By submitting mdl_request->type to MDL_ticket::create()
|
||||||
we effectively downgrade the cloned lock to the level of
|
we effectively downgrade the cloned lock to the level of
|
||||||
@ -2830,7 +2826,6 @@ void MDL_context::release_lock(enum_mdl_duration duration, MDL_ticket *ticket)
|
|||||||
lock->key.db_name(), lock->key.name()));
|
lock->key.db_name(), lock->key.name()));
|
||||||
|
|
||||||
DBUG_ASSERT(this == ticket->get_ctx());
|
DBUG_ASSERT(this == ticket->get_ctx());
|
||||||
mysql_mutex_assert_not_owner(&LOCK_open);
|
|
||||||
|
|
||||||
lock->remove_ticket(&MDL_lock::m_granted, ticket);
|
lock->remove_ticket(&MDL_lock::m_granted, ticket);
|
||||||
|
|
||||||
@ -2923,8 +2918,6 @@ void MDL_context::release_all_locks_for_name(MDL_ticket *name)
|
|||||||
|
|
||||||
void MDL_ticket::downgrade_lock(enum_mdl_type type)
|
void MDL_ticket::downgrade_lock(enum_mdl_type type)
|
||||||
{
|
{
|
||||||
mysql_mutex_assert_not_owner(&LOCK_open);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Do nothing if already downgraded. Used when we FLUSH TABLE under
|
Do nothing if already downgraded. Used when we FLUSH TABLE under
|
||||||
LOCK TABLES and a table is listed twice in LOCK TABLES list.
|
LOCK TABLES and a table is listed twice in LOCK TABLES list.
|
||||||
|
16
sql/mdl.h
16
sql/mdl.h
@ -519,17 +519,7 @@ public:
|
|||||||
|
|
||||||
virtual bool inspect_edge(MDL_context *dest) = 0;
|
virtual bool inspect_edge(MDL_context *dest) = 0;
|
||||||
virtual ~MDL_wait_for_graph_visitor();
|
virtual ~MDL_wait_for_graph_visitor();
|
||||||
MDL_wait_for_graph_visitor() :m_lock_open_count(0) {}
|
MDL_wait_for_graph_visitor() {}
|
||||||
public:
|
|
||||||
/**
|
|
||||||
XXX, hack: During deadlock search, we may need to
|
|
||||||
inspect TABLE_SHAREs and acquire LOCK_open. Since
|
|
||||||
LOCK_open is not a recursive mutex, count here how many
|
|
||||||
times we "took" it (but only take and release once).
|
|
||||||
Not using a native recursive mutex or rwlock in 5.5 for
|
|
||||||
LOCK_open since it has significant performance impacts.
|
|
||||||
*/
|
|
||||||
uint m_lock_open_count;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -980,10 +970,6 @@ extern "C" unsigned long thd_get_thread_id(const MYSQL_THD thd);
|
|||||||
*/
|
*/
|
||||||
extern "C" int thd_is_connected(MYSQL_THD thd);
|
extern "C" int thd_is_connected(MYSQL_THD thd);
|
||||||
|
|
||||||
#ifndef DBUG_OFF
|
|
||||||
extern mysql_mutex_t LOCK_open;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Start-up parameter for the maximum size of the unused MDL_lock objects cache
|
Start-up parameter for the maximum size of the unused MDL_lock objects cache
|
||||||
|
@ -262,7 +262,7 @@ uint get_table_def_key(const TABLE_LIST *table_list, const char **key)
|
|||||||
NOTES
|
NOTES
|
||||||
One gets only a list of tables for which one has any kind of privilege.
|
One gets only a list of tables for which one has any kind of privilege.
|
||||||
db and table names are allocated in result struct, so one doesn't need
|
db and table names are allocated in result struct, so one doesn't need
|
||||||
a lock on LOCK_open when traversing the return list.
|
a lock when traversing the return list.
|
||||||
|
|
||||||
RETURN VALUES
|
RETURN VALUES
|
||||||
NULL Error (Probably OOM)
|
NULL Error (Probably OOM)
|
||||||
@ -308,13 +308,13 @@ OPEN_TABLE_LIST *list_open_tables(THD *thd, const char *db, const char *wild)
|
|||||||
share->db.str)+1,
|
share->db.str)+1,
|
||||||
share->table_name.str);
|
share->table_name.str);
|
||||||
(*start_list)->in_use= 0;
|
(*start_list)->in_use= 0;
|
||||||
mysql_mutex_lock(&LOCK_open);
|
mysql_mutex_lock(&share->tdc.LOCK_table_share);
|
||||||
TABLE_SHARE::All_share_tables_list::Iterator it(share->tdc.all_tables);
|
TABLE_SHARE::All_share_tables_list::Iterator it(share->tdc.all_tables);
|
||||||
TABLE *table;
|
TABLE *table;
|
||||||
while ((table= it++))
|
while ((table= it++))
|
||||||
if (table->in_use)
|
if (table->in_use)
|
||||||
++(*start_list)->in_use;
|
++(*start_list)->in_use;
|
||||||
mysql_mutex_unlock(&LOCK_open);
|
mysql_mutex_unlock(&share->tdc.LOCK_table_share);
|
||||||
(*start_list)->locked= 0; /* Obsolete. */
|
(*start_list)->locked= 0; /* Obsolete. */
|
||||||
start_list= &(*start_list)->next;
|
start_list= &(*start_list)->next;
|
||||||
*start_list=0;
|
*start_list=0;
|
||||||
@ -335,7 +335,6 @@ void intern_close_table(TABLE *table)
|
|||||||
table->s ? table->s->db.str : "?",
|
table->s ? table->s->db.str : "?",
|
||||||
table->s ? table->s->table_name.str : "?",
|
table->s ? table->s->table_name.str : "?",
|
||||||
(long) table));
|
(long) table));
|
||||||
mysql_mutex_assert_not_owner(&LOCK_open);
|
|
||||||
|
|
||||||
free_io_cache(table);
|
free_io_cache(table);
|
||||||
delete table->triggers;
|
delete table->triggers;
|
||||||
@ -368,7 +367,7 @@ void free_io_cache(TABLE *table)
|
|||||||
|
|
||||||
@param share Table share.
|
@param share Table share.
|
||||||
|
|
||||||
@pre Caller should have LOCK_open mutex.
|
@pre Caller should have TABLE_SHARE::tdc.LOCK_table_share mutex.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void kill_delayed_threads_for_table(TABLE_SHARE *share)
|
void kill_delayed_threads_for_table(TABLE_SHARE *share)
|
||||||
@ -376,7 +375,7 @@ void kill_delayed_threads_for_table(TABLE_SHARE *share)
|
|||||||
TABLE_SHARE::All_share_tables_list::Iterator it(share->tdc.all_tables);
|
TABLE_SHARE::All_share_tables_list::Iterator it(share->tdc.all_tables);
|
||||||
TABLE *tab;
|
TABLE *tab;
|
||||||
|
|
||||||
mysql_mutex_assert_owner(&LOCK_open);
|
mysql_mutex_assert_owner(&share->tdc.LOCK_table_share);
|
||||||
|
|
||||||
if (!delayed_insert_threads)
|
if (!delayed_insert_threads)
|
||||||
return;
|
return;
|
||||||
@ -774,8 +773,6 @@ static void mark_used_tables_as_free_for_reuse(THD *thd, TABLE *table)
|
|||||||
|
|
||||||
static void close_open_tables(THD *thd)
|
static void close_open_tables(THD *thd)
|
||||||
{
|
{
|
||||||
mysql_mutex_assert_not_owner(&LOCK_open);
|
|
||||||
|
|
||||||
DBUG_PRINT("info", ("thd->open_tables: 0x%lx", (long) thd->open_tables));
|
DBUG_PRINT("info", ("thd->open_tables: 0x%lx", (long) thd->open_tables));
|
||||||
|
|
||||||
while (thd->open_tables)
|
while (thd->open_tables)
|
||||||
@ -822,7 +819,6 @@ close_all_tables_for_name(THD *thd, TABLE_SHARE *share,
|
|||||||
|
|
||||||
memcpy(key, share->table_cache_key.str, key_length);
|
memcpy(key, share->table_cache_key.str, key_length);
|
||||||
|
|
||||||
mysql_mutex_assert_not_owner(&LOCK_open);
|
|
||||||
for (TABLE **prev= &thd->open_tables; *prev; )
|
for (TABLE **prev= &thd->open_tables; *prev; )
|
||||||
{
|
{
|
||||||
TABLE *table= *prev;
|
TABLE *table= *prev;
|
||||||
@ -1018,7 +1014,6 @@ void close_thread_table(THD *thd, TABLE **table_ptr)
|
|||||||
table->s->table_name.str, (long) table));
|
table->s->table_name.str, (long) table));
|
||||||
DBUG_ASSERT(table->key_read == 0);
|
DBUG_ASSERT(table->key_read == 0);
|
||||||
DBUG_ASSERT(!table->file || table->file->inited == handler::NONE);
|
DBUG_ASSERT(!table->file || table->file->inited == handler::NONE);
|
||||||
mysql_mutex_assert_not_owner(&LOCK_open);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
The metadata lock must be released after giving back
|
The metadata lock must be released after giving back
|
||||||
@ -1049,7 +1044,10 @@ void close_thread_table(THD *thd, TABLE **table_ptr)
|
|||||||
table->file->ha_reset();
|
table->file->ha_reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Do this *before* entering the LOCK_open critical section. */
|
/*
|
||||||
|
Do this *before* entering the TABLE_SHARE::tdc.LOCK_table_share
|
||||||
|
critical section.
|
||||||
|
*/
|
||||||
if (table->file != NULL)
|
if (table->file != NULL)
|
||||||
table->file->unbind_psi();
|
table->file->unbind_psi();
|
||||||
|
|
||||||
|
@ -1115,8 +1115,6 @@ void mysql_ha_flush(THD *thd)
|
|||||||
SQL_HANDLER *hash_tables;
|
SQL_HANDLER *hash_tables;
|
||||||
DBUG_ENTER("mysql_ha_flush");
|
DBUG_ENTER("mysql_ha_flush");
|
||||||
|
|
||||||
mysql_mutex_assert_not_owner(&LOCK_open);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Don't try to flush open HANDLERs when we're working with
|
Don't try to flush open HANDLERs when we're working with
|
||||||
system tables. The main MDL context is backed up and we can't
|
system tables. The main MDL context is backed up and we can't
|
||||||
|
@ -88,9 +88,9 @@ static void print_cached_tables(void)
|
|||||||
puts("DB Table Version Thread Open Lock");
|
puts("DB Table Version Thread Open Lock");
|
||||||
|
|
||||||
tdc_it.init();
|
tdc_it.init();
|
||||||
mysql_mutex_lock(&LOCK_open);
|
|
||||||
while ((share= tdc_it.next()))
|
while ((share= tdc_it.next()))
|
||||||
{
|
{
|
||||||
|
mysql_mutex_lock(&share->tdc.LOCK_table_share);
|
||||||
TABLE_SHARE::All_share_tables_list::Iterator it(share->tdc.all_tables);
|
TABLE_SHARE::All_share_tables_list::Iterator it(share->tdc.all_tables);
|
||||||
while ((entry= it++))
|
while ((entry= it++))
|
||||||
{
|
{
|
||||||
@ -102,8 +102,8 @@ static void print_cached_tables(void)
|
|||||||
in_use ? lock_descriptions[(int)entry->reginfo.lock_type] :
|
in_use ? lock_descriptions[(int)entry->reginfo.lock_type] :
|
||||||
"Not in use");
|
"Not in use");
|
||||||
}
|
}
|
||||||
|
mysql_mutex_unlock(&share->tdc.LOCK_table_share);
|
||||||
}
|
}
|
||||||
mysql_mutex_unlock(&LOCK_open);
|
|
||||||
tdc_it.deinit();
|
tdc_it.deinit();
|
||||||
printf("\nCurrent refresh version: %ld\n", tdc_refresh_version());
|
printf("\nCurrent refresh version: %ld\n", tdc_refresh_version());
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
|
15
sql/table.cc
15
sql/table.cc
@ -3805,13 +3805,14 @@ bool TABLE_SHARE::visit_subgraph(Wait_for_flush *wait_for_flush,
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
To protect all_tables list from being concurrently modified
|
To protect all_tables list from being concurrently modified
|
||||||
while we are iterating through it we acquire LOCK_open.
|
while we are iterating through it we increment tdc.all_tables_refs.
|
||||||
This does not introduce deadlocks in the deadlock detector
|
This does not introduce deadlocks in the deadlock detector
|
||||||
because we won't try to acquire LOCK_open while
|
because we won't try to acquire tdc.LOCK_table_share while
|
||||||
holding a write-lock on MDL_lock::m_rwlock.
|
holding a write-lock on MDL_lock::m_rwlock.
|
||||||
*/
|
*/
|
||||||
if (gvisitor->m_lock_open_count++ == 0)
|
mysql_mutex_lock(&tdc.LOCK_table_share);
|
||||||
mysql_mutex_lock(&LOCK_open);
|
tdc.all_tables_refs++;
|
||||||
|
mysql_mutex_unlock(&tdc.LOCK_table_share);
|
||||||
|
|
||||||
All_share_tables_list::Iterator tables_it(tdc.all_tables);
|
All_share_tables_list::Iterator tables_it(tdc.all_tables);
|
||||||
|
|
||||||
@ -3854,8 +3855,10 @@ end_leave_node:
|
|||||||
gvisitor->leave_node(src_ctx);
|
gvisitor->leave_node(src_ctx);
|
||||||
|
|
||||||
end:
|
end:
|
||||||
if (gvisitor->m_lock_open_count-- == 1)
|
mysql_mutex_lock(&tdc.LOCK_table_share);
|
||||||
mysql_mutex_unlock(&LOCK_open);
|
if (!--tdc.all_tables_refs)
|
||||||
|
mysql_cond_broadcast(&tdc.COND_release);
|
||||||
|
mysql_mutex_unlock(&tdc.LOCK_table_share);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -616,12 +616,14 @@ struct TABLE_SHARE
|
|||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
Protects ref_count and m_flush_tickets.
|
Protects ref_count, m_flush_tickets, all_tables, free_tables, flushed,
|
||||||
|
all_tables_refs.
|
||||||
*/
|
*/
|
||||||
mysql_mutex_t LOCK_table_share;
|
mysql_mutex_t LOCK_table_share;
|
||||||
mysql_cond_t COND_release;
|
mysql_cond_t COND_release;
|
||||||
TABLE_SHARE *next, **prev; /* Link to unused shares */
|
TABLE_SHARE *next, **prev; /* Link to unused shares */
|
||||||
uint ref_count; /* How many TABLE objects uses this */
|
uint ref_count; /* How many TABLE objects uses this */
|
||||||
|
uint all_tables_refs; /* Number of refs to all_tables */
|
||||||
/**
|
/**
|
||||||
List of tickets representing threads waiting for the share to be flushed.
|
List of tickets representing threads waiting for the share to be flushed.
|
||||||
*/
|
*/
|
||||||
|
@ -69,13 +69,6 @@ static bool tdc_inited;
|
|||||||
static int32 tc_count; /**< Number of TABLE objects in table cache. */
|
static int32 tc_count; /**< Number of TABLE objects in table cache. */
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
Protects TABLE_SHARE::tdc.free_tables, TABLE_SHARE::tdc.all_tables.
|
|
||||||
*/
|
|
||||||
|
|
||||||
mysql_mutex_t LOCK_open;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Protects unused shares list.
|
Protects unused shares list.
|
||||||
|
|
||||||
@ -90,11 +83,9 @@ static mysql_rwlock_t LOCK_tdc; /**< Protects tdc_hash. */
|
|||||||
my_atomic_rwlock_t LOCK_tdc_atomics; /**< Protects tdc_version. */
|
my_atomic_rwlock_t LOCK_tdc_atomics; /**< Protects tdc_version. */
|
||||||
|
|
||||||
#ifdef HAVE_PSI_INTERFACE
|
#ifdef HAVE_PSI_INTERFACE
|
||||||
static PSI_mutex_key key_LOCK_open, key_LOCK_unused_shares,
|
static PSI_mutex_key key_LOCK_unused_shares, key_TABLE_SHARE_LOCK_table_share;
|
||||||
key_TABLE_SHARE_LOCK_table_share;
|
|
||||||
static PSI_mutex_info all_tc_mutexes[]=
|
static PSI_mutex_info all_tc_mutexes[]=
|
||||||
{
|
{
|
||||||
{ &key_LOCK_open, "LOCK_open", PSI_FLAG_GLOBAL },
|
|
||||||
{ &key_LOCK_unused_shares, "LOCK_unused_shares", PSI_FLAG_GLOBAL },
|
{ &key_LOCK_unused_shares, "LOCK_unused_shares", PSI_FLAG_GLOBAL },
|
||||||
{ &key_TABLE_SHARE_LOCK_table_share, "TABLE_SHARE::tdc.LOCK_table_share", 0 }
|
{ &key_TABLE_SHARE_LOCK_table_share, "TABLE_SHARE::tdc.LOCK_table_share", 0 }
|
||||||
};
|
};
|
||||||
@ -170,6 +161,33 @@ static void tc_remove_table(TABLE *table)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Wait for MDL deadlock detector to complete traversing tdc.all_tables.
|
||||||
|
|
||||||
|
Must be called before updating TABLE_SHARE::tdc.all_tables.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void tc_wait_for_mdl_deadlock_detector(TABLE_SHARE *share)
|
||||||
|
{
|
||||||
|
while (share->tdc.all_tables_refs)
|
||||||
|
mysql_cond_wait(&share->tdc.COND_release, &share->tdc.LOCK_table_share);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Get last element of tdc.free_tables.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static TABLE *tc_free_tables_back(TABLE_SHARE *share)
|
||||||
|
{
|
||||||
|
TABLE_SHARE::TABLE_list::Iterator it(share->tdc.free_tables);
|
||||||
|
TABLE *entry, *last= 0;
|
||||||
|
while ((entry= it++))
|
||||||
|
last= entry;
|
||||||
|
return last;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Free all unused TABLE objects.
|
Free all unused TABLE objects.
|
||||||
|
|
||||||
@ -193,9 +211,11 @@ void tc_purge(bool mark_flushed)
|
|||||||
TABLE_SHARE::TABLE_list purge_tables;
|
TABLE_SHARE::TABLE_list purge_tables;
|
||||||
|
|
||||||
tdc_it.init();
|
tdc_it.init();
|
||||||
mysql_mutex_lock(&LOCK_open);
|
|
||||||
while ((share= tdc_it.next()))
|
while ((share= tdc_it.next()))
|
||||||
{
|
{
|
||||||
|
mysql_mutex_lock(&share->tdc.LOCK_table_share);
|
||||||
|
tc_wait_for_mdl_deadlock_detector(share);
|
||||||
|
|
||||||
if (mark_flushed)
|
if (mark_flushed)
|
||||||
share->tdc.flushed= true;
|
share->tdc.flushed= true;
|
||||||
while ((table= share->tdc.free_tables.pop_front()))
|
while ((table= share->tdc.free_tables.pop_front()))
|
||||||
@ -203,9 +223,9 @@ void tc_purge(bool mark_flushed)
|
|||||||
tc_remove_table(table);
|
tc_remove_table(table);
|
||||||
purge_tables.push_front(table);
|
purge_tables.push_front(table);
|
||||||
}
|
}
|
||||||
|
mysql_mutex_unlock(&share->tdc.LOCK_table_share);
|
||||||
}
|
}
|
||||||
tdc_it.deinit();
|
tdc_it.deinit();
|
||||||
mysql_mutex_unlock(&LOCK_open);
|
|
||||||
|
|
||||||
while ((table= purge_tables.pop_front()))
|
while ((table= purge_tables.pop_front()))
|
||||||
intern_close_table(table);
|
intern_close_table(table);
|
||||||
@ -232,9 +252,10 @@ void tc_add_table(THD *thd, TABLE *table)
|
|||||||
{
|
{
|
||||||
bool need_purge;
|
bool need_purge;
|
||||||
DBUG_ASSERT(table->in_use == thd);
|
DBUG_ASSERT(table->in_use == thd);
|
||||||
mysql_mutex_lock(&LOCK_open);
|
mysql_mutex_lock(&table->s->tdc.LOCK_table_share);
|
||||||
|
tc_wait_for_mdl_deadlock_detector(table->s);
|
||||||
table->s->tdc.all_tables.push_front(table);
|
table->s->tdc.all_tables.push_front(table);
|
||||||
mysql_mutex_unlock(&LOCK_open);
|
mysql_mutex_unlock(&table->s->tdc.LOCK_table_share);
|
||||||
|
|
||||||
/* If we have too many TABLE instances around, try to get rid of them */
|
/* If we have too many TABLE instances around, try to get rid of them */
|
||||||
my_atomic_rwlock_wrlock(&LOCK_tdc_atomics);
|
my_atomic_rwlock_wrlock(&LOCK_tdc_atomics);
|
||||||
@ -243,31 +264,48 @@ void tc_add_table(THD *thd, TABLE *table)
|
|||||||
|
|
||||||
if (need_purge)
|
if (need_purge)
|
||||||
{
|
{
|
||||||
TABLE *purge_table= 0;
|
TABLE_SHARE *purge_share= 0;
|
||||||
TABLE_SHARE *share;
|
TABLE_SHARE *share;
|
||||||
|
TABLE *entry;
|
||||||
|
ulonglong purge_time;
|
||||||
TDC_iterator tdc_it;
|
TDC_iterator tdc_it;
|
||||||
|
|
||||||
tdc_it.init();
|
tdc_it.init();
|
||||||
mysql_mutex_lock(&LOCK_open);
|
|
||||||
while ((share= tdc_it.next()))
|
while ((share= tdc_it.next()))
|
||||||
{
|
{
|
||||||
TABLE_SHARE::TABLE_list::Iterator it(share->tdc.free_tables);
|
mysql_mutex_lock(&share->tdc.LOCK_table_share);
|
||||||
TABLE *entry;
|
if ((entry= tc_free_tables_back(share)) &&
|
||||||
while ((entry= it++))
|
(!purge_share || entry->tc_time < purge_time))
|
||||||
if (!purge_table || entry->tc_time < purge_table->tc_time)
|
{
|
||||||
purge_table= entry;
|
purge_share= share;
|
||||||
|
purge_time= entry->tc_time;
|
||||||
|
}
|
||||||
|
mysql_mutex_unlock(&share->tdc.LOCK_table_share);
|
||||||
}
|
}
|
||||||
tdc_it.deinit();
|
|
||||||
|
|
||||||
if (purge_table)
|
if (purge_share)
|
||||||
{
|
{
|
||||||
purge_table->s->tdc.free_tables.remove(purge_table);
|
mysql_mutex_lock(&purge_share->tdc.LOCK_table_share);
|
||||||
tc_remove_table(purge_table);
|
tc_wait_for_mdl_deadlock_detector(purge_share);
|
||||||
mysql_mutex_unlock(&LOCK_open);
|
tdc_it.deinit();
|
||||||
intern_close_table(purge_table);
|
/*
|
||||||
|
It may happen that oldest table was acquired meanwhile. In this case
|
||||||
|
just go ahead, number of objects in table cache will normalize
|
||||||
|
eventually.
|
||||||
|
*/
|
||||||
|
if ((entry= tc_free_tables_back(purge_share)) &&
|
||||||
|
entry->tc_time == purge_time)
|
||||||
|
{
|
||||||
|
entry->s->tdc.free_tables.remove(entry);
|
||||||
|
tc_remove_table(entry);
|
||||||
|
mysql_mutex_unlock(&purge_share->tdc.LOCK_table_share);
|
||||||
|
intern_close_table(entry);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
mysql_mutex_unlock(&purge_share->tdc.LOCK_table_share);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
mysql_mutex_unlock(&LOCK_open);
|
tdc_it.deinit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -292,9 +330,9 @@ static TABLE *tc_acquire_table(THD *thd, TABLE_SHARE *share)
|
|||||||
{
|
{
|
||||||
TABLE *table;
|
TABLE *table;
|
||||||
|
|
||||||
mysql_mutex_lock(&LOCK_open);
|
mysql_mutex_lock(&share->tdc.LOCK_table_share);
|
||||||
table= share->tdc.free_tables.pop_front();
|
table= share->tdc.free_tables.pop_front();
|
||||||
mysql_mutex_unlock(&LOCK_open);
|
mysql_mutex_unlock(&share->tdc.LOCK_table_share);
|
||||||
|
|
||||||
if (table)
|
if (table)
|
||||||
{
|
{
|
||||||
@ -328,7 +366,7 @@ static TABLE *tc_acquire_table(THD *thd, TABLE_SHARE *share)
|
|||||||
@note Another thread may mark share for purge any moment (even
|
@note Another thread may mark share for purge any moment (even
|
||||||
after version check). It means to-be-purged object may go to
|
after version check). It means to-be-purged object may go to
|
||||||
unused lists. This other thread is expected to call tc_purge(),
|
unused lists. This other thread is expected to call tc_purge(),
|
||||||
which is synchronized with us on LOCK_open.
|
which is synchronized with us on TABLE_SHARE::tdc.LOCK_table_share.
|
||||||
|
|
||||||
@return
|
@return
|
||||||
@retval true object purged
|
@retval true object purged
|
||||||
@ -342,17 +380,17 @@ bool tc_release_table(TABLE *table)
|
|||||||
|
|
||||||
if (table->needs_reopen() || tc_records() > tc_size)
|
if (table->needs_reopen() || tc_records() > tc_size)
|
||||||
{
|
{
|
||||||
mysql_mutex_lock(&LOCK_open);
|
mysql_mutex_lock(&table->s->tdc.LOCK_table_share);
|
||||||
goto purge;
|
goto purge;
|
||||||
}
|
}
|
||||||
|
|
||||||
table->tc_time= my_interval_timer();
|
table->tc_time= my_interval_timer();
|
||||||
|
|
||||||
mysql_mutex_lock(&LOCK_open);
|
mysql_mutex_lock(&table->s->tdc.LOCK_table_share);
|
||||||
if (table->s->tdc.flushed)
|
if (table->s->tdc.flushed)
|
||||||
goto purge;
|
goto purge;
|
||||||
/*
|
/*
|
||||||
in_use doesn't really need protection of LOCK_open, but must be reset after
|
in_use doesn't really need mutex protection, but must be reset after
|
||||||
checking tdc.flushed and before this table appears in free_tables.
|
checking tdc.flushed and before this table appears in free_tables.
|
||||||
Resetting in_use is needed only for print_cached_tables() and
|
Resetting in_use is needed only for print_cached_tables() and
|
||||||
list_open_tables().
|
list_open_tables().
|
||||||
@ -360,12 +398,13 @@ bool tc_release_table(TABLE *table)
|
|||||||
table->in_use= 0;
|
table->in_use= 0;
|
||||||
/* Add table to the list of unused TABLE objects for this share. */
|
/* Add table to the list of unused TABLE objects for this share. */
|
||||||
table->s->tdc.free_tables.push_front(table);
|
table->s->tdc.free_tables.push_front(table);
|
||||||
mysql_mutex_unlock(&LOCK_open);
|
mysql_mutex_unlock(&table->s->tdc.LOCK_table_share);
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
purge:
|
purge:
|
||||||
|
tc_wait_for_mdl_deadlock_detector(table->s);
|
||||||
tc_remove_table(table);
|
tc_remove_table(table);
|
||||||
mysql_mutex_unlock(&LOCK_open);
|
mysql_mutex_unlock(&table->s->tdc.LOCK_table_share);
|
||||||
table->in_use= 0;
|
table->in_use= 0;
|
||||||
intern_close_table(table);
|
intern_close_table(table);
|
||||||
return true;
|
return true;
|
||||||
@ -446,13 +485,6 @@ int tdc_init(void)
|
|||||||
init_tc_psi_keys();
|
init_tc_psi_keys();
|
||||||
#endif
|
#endif
|
||||||
tdc_inited= true;
|
tdc_inited= true;
|
||||||
mysql_mutex_init(key_LOCK_open, &LOCK_open, MY_MUTEX_INIT_FAST);
|
|
||||||
mysql_mutex_record_order(&LOCK_active_mi, &LOCK_open);
|
|
||||||
/*
|
|
||||||
We must have LOCK_open before LOCK_global_system_variables because
|
|
||||||
LOCK_open is held while sql_plugin.cc::intern_sys_var_ptr() is called.
|
|
||||||
*/
|
|
||||||
mysql_mutex_record_order(&LOCK_open, &LOCK_global_system_variables);
|
|
||||||
mysql_mutex_init(key_LOCK_unused_shares, &LOCK_unused_shares,
|
mysql_mutex_init(key_LOCK_unused_shares, &LOCK_unused_shares,
|
||||||
MY_MUTEX_INIT_FAST);
|
MY_MUTEX_INIT_FAST);
|
||||||
mysql_rwlock_init(key_rwlock_LOCK_tdc, &LOCK_tdc);
|
mysql_rwlock_init(key_rwlock_LOCK_tdc, &LOCK_tdc);
|
||||||
@ -505,7 +537,6 @@ void tdc_deinit(void)
|
|||||||
my_atomic_rwlock_destroy(&LOCK_tdc_atomics);
|
my_atomic_rwlock_destroy(&LOCK_tdc_atomics);
|
||||||
mysql_rwlock_destroy(&LOCK_tdc);
|
mysql_rwlock_destroy(&LOCK_tdc);
|
||||||
mysql_mutex_destroy(&LOCK_unused_shares);
|
mysql_mutex_destroy(&LOCK_unused_shares);
|
||||||
mysql_mutex_destroy(&LOCK_open);
|
|
||||||
}
|
}
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
@ -575,6 +606,7 @@ void tdc_init_share(TABLE_SHARE *share)
|
|||||||
tdc_assign_new_table_id(share);
|
tdc_assign_new_table_id(share);
|
||||||
share->tdc.version= tdc_refresh_version();
|
share->tdc.version= tdc_refresh_version();
|
||||||
share->tdc.flushed= false;
|
share->tdc.flushed= false;
|
||||||
|
share->tdc.all_tables_refs= 0;
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -590,6 +622,7 @@ void tdc_deinit_share(TABLE_SHARE *share)
|
|||||||
DBUG_ASSERT(share->tdc.m_flush_tickets.is_empty());
|
DBUG_ASSERT(share->tdc.m_flush_tickets.is_empty());
|
||||||
DBUG_ASSERT(share->tdc.all_tables.is_empty());
|
DBUG_ASSERT(share->tdc.all_tables.is_empty());
|
||||||
DBUG_ASSERT(share->tdc.free_tables.is_empty());
|
DBUG_ASSERT(share->tdc.free_tables.is_empty());
|
||||||
|
DBUG_ASSERT(share->tdc.all_tables_refs == 0);
|
||||||
mysql_cond_destroy(&share->tdc.COND_release);
|
mysql_cond_destroy(&share->tdc.COND_release);
|
||||||
mysql_mutex_destroy(&share->tdc.LOCK_table_share);
|
mysql_mutex_destroy(&share->tdc.LOCK_table_share);
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
@ -826,7 +859,8 @@ void tdc_release_share(TABLE_SHARE *share)
|
|||||||
if (share->tdc.ref_count > 1)
|
if (share->tdc.ref_count > 1)
|
||||||
{
|
{
|
||||||
share->tdc.ref_count--;
|
share->tdc.ref_count--;
|
||||||
mysql_cond_broadcast(&share->tdc.COND_release);
|
if (!share->is_view)
|
||||||
|
mysql_cond_broadcast(&share->tdc.COND_release);
|
||||||
mysql_mutex_unlock(&share->tdc.LOCK_table_share);
|
mysql_mutex_unlock(&share->tdc.LOCK_table_share);
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
@ -954,13 +988,14 @@ bool tdc_remove_table(THD *thd, enum_tdc_remove_table_type remove_type,
|
|||||||
I_P_List <TABLE, TABLE_share> purge_tables;
|
I_P_List <TABLE, TABLE_share> purge_tables;
|
||||||
uint my_refs= 1;
|
uint my_refs= 1;
|
||||||
|
|
||||||
mysql_mutex_lock(&LOCK_open);
|
mysql_mutex_lock(&share->tdc.LOCK_table_share);
|
||||||
|
tc_wait_for_mdl_deadlock_detector(share);
|
||||||
/*
|
/*
|
||||||
Set share's version to zero in order to ensure that it gets
|
Mark share flushed in order to ensure that it gets
|
||||||
automatically deleted once it is no longer referenced.
|
automatically deleted once it is no longer referenced.
|
||||||
|
|
||||||
Note that code in TABLE_SHARE::wait_for_old_version() assumes that
|
Note that code in TABLE_SHARE::wait_for_old_version() assumes that
|
||||||
incrementing of refresh_version is followed by purge of unused table
|
marking share flushed is followed by purge of unused table
|
||||||
shares.
|
shares.
|
||||||
*/
|
*/
|
||||||
if (remove_type != TDC_RT_REMOVE_NOT_OWN_KEEP_SHARE)
|
if (remove_type != TDC_RT_REMOVE_NOT_OWN_KEEP_SHARE)
|
||||||
@ -985,7 +1020,7 @@ bool tdc_remove_table(THD *thd, enum_tdc_remove_table_type remove_type,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
DBUG_ASSERT(share->tdc.all_tables.is_empty() || remove_type != TDC_RT_REMOVE_ALL);
|
DBUG_ASSERT(share->tdc.all_tables.is_empty() || remove_type != TDC_RT_REMOVE_ALL);
|
||||||
mysql_mutex_unlock(&LOCK_open);
|
mysql_mutex_unlock(&share->tdc.LOCK_table_share);
|
||||||
|
|
||||||
while ((table= purge_tables.pop_front()))
|
while ((table= purge_tables.pop_front()))
|
||||||
intern_close_table(table);
|
intern_close_table(table);
|
||||||
|
@ -26,7 +26,6 @@ enum enum_tdc_remove_table_type
|
|||||||
|
|
||||||
extern ulong tdc_size;
|
extern ulong tdc_size;
|
||||||
extern ulong tc_size;
|
extern ulong tc_size;
|
||||||
extern mysql_mutex_t LOCK_open; /* FIXME: make private */
|
|
||||||
|
|
||||||
extern int tdc_init(void);
|
extern int tdc_init(void);
|
||||||
extern void tdc_start_shutdown(void);
|
extern void tdc_start_shutdown(void);
|
||||||
|
@ -3119,14 +3119,6 @@ int ha_federated::real_connect()
|
|||||||
String sql_query(buffer, sizeof(buffer), &my_charset_bin);
|
String sql_query(buffer, sizeof(buffer), &my_charset_bin);
|
||||||
DBUG_ENTER("ha_federated::real_connect");
|
DBUG_ENTER("ha_federated::real_connect");
|
||||||
|
|
||||||
/*
|
|
||||||
Bug#25679
|
|
||||||
Ensure that we do not hold the LOCK_open mutex while attempting
|
|
||||||
to establish Federated connection to guard against a trivial
|
|
||||||
Denial of Service scenerio.
|
|
||||||
*/
|
|
||||||
mysql_mutex_assert_not_owner(&LOCK_open);
|
|
||||||
|
|
||||||
DBUG_ASSERT(mysql == NULL);
|
DBUG_ASSERT(mysql == NULL);
|
||||||
|
|
||||||
if (!(mysql= mysql_init(NULL)))
|
if (!(mysql= mysql_init(NULL)))
|
||||||
|
@ -3384,14 +3384,6 @@ int ha_federatedx::create(const char *name, TABLE *table_arg,
|
|||||||
{
|
{
|
||||||
FEDERATEDX_SERVER server;
|
FEDERATEDX_SERVER server;
|
||||||
|
|
||||||
/*
|
|
||||||
Bug#25679
|
|
||||||
Ensure that we do not hold the LOCK_open mutex while attempting
|
|
||||||
to establish FederatedX connection to guard against a trivial
|
|
||||||
Denial of Service scenerio.
|
|
||||||
*/
|
|
||||||
mysql_mutex_assert_not_owner(&LOCK_open);
|
|
||||||
|
|
||||||
fill_server(thd->mem_root, &server, &tmp_share, create_info->table_charset);
|
fill_server(thd->mem_root, &server, &tmp_share, create_info->table_charset);
|
||||||
|
|
||||||
#ifndef DBUG_OFF
|
#ifndef DBUG_OFF
|
||||||
|
Loading…
x
Reference in New Issue
Block a user