diff options
author | Sergey Vojtovich <svoj@mariadb.org> | 2014-02-13 10:44:10 +0400 |
---|---|---|
committer | Sergey Vojtovich <svoj@mariadb.org> | 2014-02-13 10:44:10 +0400 |
commit | 048e9c40a661476d1b742f61d692f211acbd24d2 (patch) | |
tree | 8f54dde52aa39fd3a5ac523764820747508b0975 /sql/sql_base.cc | |
parent | a25d87e50f2636263d03246ba8a7ca827f43c48b (diff) | |
download | mariadb-git-048e9c40a661476d1b742f61d692f211acbd24d2.tar.gz |
MDEV-5492 - Reduce usage of LOCK_open: TABLE::in_use
Move TABLE::in_use out of LOCK_open.
This is done with assumtion that foreign threads accessing TABLE::in_use
will only need consistent value _after_ marking table for flush and purging
unused table instances. In this case TABLE::in_use will always point to a
valid thread object.
Previously FLUSH TABLES thread may wait for tables flushed subsequently by
concurrent threads which breaks the above assumption, e.g.:
open tables: t1 (version= 1)
thr1 (FLUSH TABLES): refresh_version++
thr1 (FLUSH TABLES): purge table cache
open tables: none
thr2 (SELECT * FROM t1): open tables: t1
open tables: t1 (version= 2)
thr2 (FLUSH TABLES): refresh_version++
thr2 (FLUSH TABLES): purge table cache
thr1 (FLUSH TABLES): wait for old tables (including t1 with version 2)
It is fixed so that FLUSH TABLES waits only for tables that were open
heretofore.
Diffstat (limited to 'sql/sql_base.cc')
-rw-r--r-- | sql/sql_base.cc | 22 |
1 files changed, 13 insertions, 9 deletions
diff --git a/sql/sql_base.cc b/sql/sql_base.cc index f4ff9f2fc75..b0e121018fc 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -385,7 +385,8 @@ void kill_delayed_threads_for_table(TABLE_SHARE *share) { THD *in_use= tab->in_use; - if (in_use && (in_use->system_thread & SYSTEM_THREAD_DELAYED_INSERT) && + DBUG_ASSERT(in_use && tab->s->tdc.flushed); + if ((in_use->system_thread & SYSTEM_THREAD_DELAYED_INSERT) && ! in_use->killed) { in_use->killed= KILL_SYSTEM_THREAD; @@ -426,9 +427,12 @@ bool close_cached_tables(THD *thd, TABLE_LIST *tables, { bool result= FALSE; struct timespec abstime; + ulong refresh_version; DBUG_ENTER("close_cached_tables"); DBUG_ASSERT(thd || (!wait_for_refresh && !tables)); + refresh_version= tdc_increment_refresh_version(); + if (!tables) { /* @@ -438,13 +442,12 @@ bool close_cached_tables(THD *thd, TABLE_LIST *tables, incrementing of refresh_version is followed by purge of unused table shares. */ - tdc_increment_refresh_version(); kill_delayed_threads(); /* Get rid of all unused TABLE and TABLE_SHARE instances. By doing this we automatically close all tables which were marked as "old". */ - tc_purge(); + tc_purge(true); /* Free table shares which were not freed implicitly by loop above. */ tdc_purge(true); } @@ -526,7 +529,7 @@ bool close_cached_tables(THD *thd, TABLE_LIST *tables, while ((share= tdc_it.next())) { mysql_mutex_lock(&share->tdc.LOCK_table_share); - if (share->has_old_version()) + if (share->tdc.flushed && share->tdc.version < refresh_version) { /* wait_for_old_version() will unlock mutex and free share */ found= true; @@ -554,7 +557,8 @@ bool close_cached_tables(THD *thd, TABLE_LIST *tables, if (thd->killed) break; if (tdc_wait_for_old_version(thd, table->db, table->table_name, timeout, - MDL_wait_for_subgraph::DEADLOCK_WEIGHT_DDL)) + MDL_wait_for_subgraph::DEADLOCK_WEIGHT_DDL, + refresh_version)) { result= TRUE; break; @@ -1754,7 +1758,7 @@ bool wait_while_table_is_used(THD *thd, TABLE *table, DBUG_ENTER("wait_while_table_is_used"); DBUG_PRINT("enter", ("table: '%s' share: 0x%lx db_stat: %u version: %lu", table->s->table_name.str, (ulong) table->s, - table->db_stat, table->s->version)); + table->db_stat, table->s->tdc.version)); if (thd->mdl_context.upgrade_shared_lock( table->mdl_ticket, MDL_EXCLUSIVE, @@ -2321,7 +2325,7 @@ retry_share: /* Check if this TABLE_SHARE-object corresponds to a view. Note, that there is - no need to call TABLE_SHARE::has_old_version() as we do for regular tables, + no need to check TABLE_SHARE::tdc.flushed as we do for regular tables, because view shares are always up to date. */ if (share->is_view) @@ -2362,7 +2366,7 @@ retry_share: if (!(flags & MYSQL_OPEN_IGNORE_FLUSH)) { - if (share->has_old_version()) + if (share->tdc.flushed) { /* We already have an MDL lock. But we have encountered an old @@ -2394,7 +2398,7 @@ retry_share: goto retry_share; } - if (thd->open_tables && thd->open_tables->s->version != share->version) + if (thd->open_tables && thd->open_tables->s->tdc.flushed) { /* If the version changes while we're opening the tables, |