MDEV-5403 - Reduce usage of LOCK_open: tc_count
Lock-free tc_count.
This commit is contained in:
parent
103643d87a
commit
a25d87e50f
@ -64,11 +64,11 @@ static int64 tdc_version; /* Increments on each reload */
|
|||||||
static int64 last_table_id;
|
static int64 last_table_id;
|
||||||
static bool tdc_inited;
|
static bool tdc_inited;
|
||||||
|
|
||||||
static uint tc_count; /**< Number of TABLE objects in table cache. */
|
static int32 tc_count; /**< Number of TABLE objects in table cache. */
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Protects tc_count, TABLE_SHARE::tdc.free_tables, TABLE_SHARE::tdc.all_tables,
|
Protects TABLE_SHARE::tdc.free_tables, TABLE_SHARE::tdc.all_tables,
|
||||||
TABLE::in_use.
|
TABLE::in_use.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -122,8 +122,8 @@ static void init_tc_psi_keys(void)
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Auxiliary routines for manipulating with per-share used/unused and
|
Auxiliary routines for manipulating with per-share all/unused lists
|
||||||
global unused lists of TABLE objects and tc_count counter.
|
and tc_count counter.
|
||||||
Responsible for preserving invariants between those lists, counter
|
Responsible for preserving invariants between those lists, counter
|
||||||
and TABLE::in_use member.
|
and TABLE::in_use member.
|
||||||
In fact those routines implement sort of implicit table cache as
|
In fact those routines implement sort of implicit table cache as
|
||||||
@ -133,13 +133,31 @@ static void init_tc_psi_keys(void)
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
Get number of TABLE objects (used and unused) in table cache.
|
Get number of TABLE objects (used and unused) in table cache.
|
||||||
|
|
||||||
@todo Protect tc_count so it is read atomically.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
uint tc_records(void)
|
uint tc_records(void)
|
||||||
{
|
{
|
||||||
return tc_count;
|
uint count;
|
||||||
|
my_atomic_rwlock_rdlock(&LOCK_tdc_atomics);
|
||||||
|
count= my_atomic_load32(&tc_count);
|
||||||
|
my_atomic_rwlock_rdunlock(&LOCK_tdc_atomics);
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Remove TABLE object from table cache.
|
||||||
|
|
||||||
|
- decrement tc_count
|
||||||
|
- remove object from TABLE_SHARE::tdc.all_tables
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void tc_remove_table(TABLE *table)
|
||||||
|
{
|
||||||
|
my_atomic_rwlock_wrlock(&LOCK_tdc_atomics);
|
||||||
|
my_atomic_add32(&tc_count, -1);
|
||||||
|
my_atomic_rwlock_wrunlock(&LOCK_tdc_atomics);
|
||||||
|
table->s->tdc.all_tables.remove(table);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -171,9 +189,8 @@ void tc_purge(void)
|
|||||||
{
|
{
|
||||||
while ((table= share->tdc.free_tables.pop_front()))
|
while ((table= share->tdc.free_tables.pop_front()))
|
||||||
{
|
{
|
||||||
share->tdc.all_tables.remove(table);
|
tc_remove_table(table);
|
||||||
purge_tables.push_front(table);
|
purge_tables.push_front(table);
|
||||||
tc_count--;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tdc_it.deinit();
|
tdc_it.deinit();
|
||||||
@ -247,47 +264,48 @@ static void check_unused(THD *thd)
|
|||||||
|
|
||||||
void tc_add_table(THD *thd, TABLE *table)
|
void tc_add_table(THD *thd, TABLE *table)
|
||||||
{
|
{
|
||||||
|
bool need_purge;
|
||||||
DBUG_ASSERT(table->in_use == thd);
|
DBUG_ASSERT(table->in_use == thd);
|
||||||
mysql_mutex_lock(&LOCK_open);
|
mysql_mutex_lock(&LOCK_open);
|
||||||
table->s->tdc.all_tables.push_front(table);
|
table->s->tdc.all_tables.push_front(table);
|
||||||
|
mysql_mutex_unlock(&LOCK_open);
|
||||||
|
|
||||||
/* 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 */
|
||||||
if (tc_count == tc_size)
|
my_atomic_rwlock_wrlock(&LOCK_tdc_atomics);
|
||||||
|
need_purge= my_atomic_add32(&tc_count, 1) >= (int32) tc_size;
|
||||||
|
my_atomic_rwlock_wrunlock(&LOCK_tdc_atomics);
|
||||||
|
|
||||||
|
if (need_purge)
|
||||||
{
|
{
|
||||||
|
TABLE *purge_table= 0;
|
||||||
|
TABLE_SHARE *share;
|
||||||
TDC_iterator tdc_it;
|
TDC_iterator tdc_it;
|
||||||
mysql_mutex_unlock(&LOCK_open);
|
|
||||||
|
|
||||||
tdc_it.init();
|
tdc_it.init();
|
||||||
mysql_mutex_lock(&LOCK_open);
|
mysql_mutex_lock(&LOCK_open);
|
||||||
if (tc_count == tc_size)
|
while ((share= tdc_it.next()))
|
||||||
{
|
{
|
||||||
TABLE *purge_table= 0;
|
TABLE_SHARE::TABLE_list::Iterator it(share->tdc.free_tables);
|
||||||
TABLE_SHARE *share;
|
TABLE *entry;
|
||||||
while ((share= tdc_it.next()))
|
while ((entry= it++))
|
||||||
{
|
if (!purge_table || entry->tc_time < purge_table->tc_time)
|
||||||
TABLE_SHARE::TABLE_list::Iterator it(share->tdc.free_tables);
|
purge_table= entry;
|
||||||
TABLE *entry;
|
|
||||||
while ((entry= it++))
|
|
||||||
if (!purge_table || entry->tc_time < purge_table->tc_time)
|
|
||||||
purge_table= entry;
|
|
||||||
}
|
|
||||||
if (purge_table)
|
|
||||||
{
|
|
||||||
tdc_it.deinit();
|
|
||||||
purge_table->s->tdc.free_tables.remove(purge_table);
|
|
||||||
purge_table->s->tdc.all_tables.remove(purge_table);
|
|
||||||
mysql_rwlock_rdlock(&LOCK_flush);
|
|
||||||
mysql_mutex_unlock(&LOCK_open);
|
|
||||||
intern_close_table(purge_table);
|
|
||||||
mysql_rwlock_unlock(&LOCK_flush);
|
|
||||||
check_unused(thd);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
tdc_it.deinit();
|
tdc_it.deinit();
|
||||||
|
|
||||||
|
if (purge_table)
|
||||||
|
{
|
||||||
|
purge_table->s->tdc.free_tables.remove(purge_table);
|
||||||
|
tc_remove_table(purge_table);
|
||||||
|
mysql_rwlock_rdlock(&LOCK_flush);
|
||||||
|
mysql_mutex_unlock(&LOCK_open);
|
||||||
|
intern_close_table(purge_table);
|
||||||
|
mysql_rwlock_unlock(&LOCK_flush);
|
||||||
|
check_unused(thd);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
mysql_mutex_unlock(&LOCK_open);
|
||||||
}
|
}
|
||||||
/* Nothing to evict, increment tc_count. */
|
|
||||||
tc_count++;
|
|
||||||
mysql_mutex_unlock(&LOCK_open);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -359,25 +377,32 @@ bool tc_release_table(TABLE *table)
|
|||||||
DBUG_ASSERT(table->in_use);
|
DBUG_ASSERT(table->in_use);
|
||||||
DBUG_ASSERT(table->file);
|
DBUG_ASSERT(table->file);
|
||||||
|
|
||||||
|
if (table->needs_reopen() || tc_records() > tc_size)
|
||||||
|
{
|
||||||
|
mysql_mutex_lock(&LOCK_open);
|
||||||
|
table->in_use= 0;
|
||||||
|
goto purge;
|
||||||
|
}
|
||||||
|
|
||||||
table->tc_time= my_interval_timer();
|
table->tc_time= my_interval_timer();
|
||||||
|
|
||||||
mysql_mutex_lock(&LOCK_open);
|
mysql_mutex_lock(&LOCK_open);
|
||||||
table->in_use= 0;
|
table->in_use= 0;
|
||||||
if (table->s->has_old_version() || table->needs_reopen() || tc_count > tc_size)
|
if (table->s->has_old_version())
|
||||||
{
|
goto purge;
|
||||||
tc_count--;
|
|
||||||
table->s->tdc.all_tables.remove(table);
|
|
||||||
mysql_rwlock_rdlock(&LOCK_flush);
|
|
||||||
mysql_mutex_unlock(&LOCK_open);
|
|
||||||
intern_close_table(table);
|
|
||||||
mysql_rwlock_unlock(&LOCK_flush);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
/* 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(&LOCK_open);
|
||||||
check_unused(thd);
|
check_unused(thd);
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
purge:
|
||||||
|
tc_remove_table(table);
|
||||||
|
mysql_rwlock_rdlock(&LOCK_flush);
|
||||||
|
mysql_mutex_unlock(&LOCK_open);
|
||||||
|
intern_close_table(table);
|
||||||
|
mysql_rwlock_unlock(&LOCK_flush);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -987,8 +1012,7 @@ bool tdc_remove_table(THD *thd, enum_tdc_remove_table_type remove_type,
|
|||||||
|
|
||||||
while ((table= share->tdc.free_tables.pop_front()))
|
while ((table= share->tdc.free_tables.pop_front()))
|
||||||
{
|
{
|
||||||
share->tdc.all_tables.remove(table);
|
tc_remove_table(table);
|
||||||
tc_count--;
|
|
||||||
purge_tables.push_front(table);
|
purge_tables.push_front(table);
|
||||||
}
|
}
|
||||||
mysql_rwlock_rdlock(&LOCK_flush);
|
mysql_rwlock_rdlock(&LOCK_flush);
|
||||||
@ -1052,7 +1076,7 @@ ulong tdc_refresh_version(void)
|
|||||||
{
|
{
|
||||||
my_atomic_rwlock_rdlock(&LOCK_tdc_atomics);
|
my_atomic_rwlock_rdlock(&LOCK_tdc_atomics);
|
||||||
ulong v= my_atomic_load64(&tdc_version);
|
ulong v= my_atomic_load64(&tdc_version);
|
||||||
my_atomic_rwlock_wrunlock(&LOCK_tdc_atomics);
|
my_atomic_rwlock_rdunlock(&LOCK_tdc_atomics);
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user