[Commits] d6f760d: MDEV-10296 - Multi-instance table cache

Sergey Vojtovich svoj at mariadb.org
Thu Sep 8 15:02:51 EEST 2016


revision-id: d6f760d344f45177936c72cb65ba1ffff596710e (mariadb-10.1.8-230-gd6f760d)
parent(s): 9f7e77b5414b5b2ef9b5f50f131966821fefb9c7
committer: Sergey Vojtovich
timestamp: 2016-09-08 16:02:49 +0400
message:

MDEV-10296 - Multi-instance table cache

Table cache instances autosizing.

---
 mysql-test/r/mysqld--help.result                   |  4 +-
 .../sys_vars/r/sysvars_server_embedded.result      |  6 +--
 .../sys_vars/r/sysvars_server_notembedded.result   |  6 +--
 sql/sys_vars.cc                                    |  4 +-
 sql/table.h                                        |  1 +
 sql/table_cache.cc                                 | 61 ++++++++++++++++++++--
 6 files changed, 67 insertions(+), 15 deletions(-)

diff --git a/mysql-test/r/mysqld--help.result b/mysql-test/r/mysqld--help.result
index e742de8..8a93381 100644
--- a/mysql-test/r/mysqld--help.result
+++ b/mysql-test/r/mysqld--help.result
@@ -1091,7 +1091,7 @@ The following options may be given as the first argument:
  --table-open-cache=# 
  The number of cached open tables
  --table-open-cache-instances=# 
- The number of table cache instances
+ Maximum number of table cache instances
  --tc-heuristic-recover=name 
  Decision to use in heuristic recover process. One of: OFF,
  COMMIT, ROLLBACK
@@ -1458,7 +1458,7 @@ sysdate-is-now FALSE
 table-cache 431
 table-definition-cache 400
 table-open-cache 431
-table-open-cache-instances 1
+table-open-cache-instances 8
 tc-heuristic-recover OFF
 thread-cache-size 151
 thread-pool-idle-timeout 60
diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result b/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result
index bdc8f3c..361b61f 100644
--- a/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result
+++ b/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result
@@ -3889,12 +3889,12 @@ READ_ONLY	NO
 COMMAND_LINE_ARGUMENT	REQUIRED
 VARIABLE_NAME	TABLE_OPEN_CACHE_INSTANCES
 SESSION_VALUE	NULL
-GLOBAL_VALUE	1
+GLOBAL_VALUE	8
 GLOBAL_VALUE_ORIGIN	COMPILE-TIME
-DEFAULT_VALUE	1
+DEFAULT_VALUE	8
 VARIABLE_SCOPE	GLOBAL
 VARIABLE_TYPE	BIGINT UNSIGNED
-VARIABLE_COMMENT	The number of table cache instances
+VARIABLE_COMMENT	Maximum number of table cache instances
 NUMERIC_MIN_VALUE	1
 NUMERIC_MAX_VALUE	64
 NUMERIC_BLOCK_SIZE	1
diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result
index 5b676f3..a36cc85 100644
--- a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result
+++ b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result
@@ -4659,12 +4659,12 @@ READ_ONLY	NO
 COMMAND_LINE_ARGUMENT	REQUIRED
 VARIABLE_NAME	TABLE_OPEN_CACHE_INSTANCES
 SESSION_VALUE	NULL
-GLOBAL_VALUE	1
+GLOBAL_VALUE	8
 GLOBAL_VALUE_ORIGIN	COMPILE-TIME
-DEFAULT_VALUE	1
+DEFAULT_VALUE	8
 VARIABLE_SCOPE	GLOBAL
 VARIABLE_TYPE	BIGINT UNSIGNED
-VARIABLE_COMMENT	The number of table cache instances
+VARIABLE_COMMENT	Maximum number of table cache instances
 NUMERIC_MIN_VALUE	1
 NUMERIC_MAX_VALUE	64
 NUMERIC_BLOCK_SIZE	1
diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc
index df59cf8..191bee3 100644
--- a/sql/sys_vars.cc
+++ b/sql/sys_vars.cc
@@ -3220,9 +3220,9 @@ static Sys_var_ulong Sys_table_cache_size(
        ON_UPDATE(fix_table_open_cache));
 
 static Sys_var_ulong Sys_table_cache_instances(
-       "table_open_cache_instances", "The number of table cache instances",
+       "table_open_cache_instances", "Maximum number of table cache instances",
        READ_ONLY GLOBAL_VAR(tc_instances), CMD_LINE(REQUIRED_ARG),
-       VALID_RANGE(1, 64), DEFAULT(1), BLOCK_SIZE(1));
+       VALID_RANGE(1, 64), DEFAULT(8), BLOCK_SIZE(1));
 
 static Sys_var_ulong Sys_thread_cache_size(
        "thread_cache_size",
diff --git a/sql/table.h b/sql/table.h
index 7e2c2dd..b8f9fc2 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -1027,6 +1027,7 @@ struct TABLE
 
 public:
 
+  uint32 instance; /** Table cache instance this TABLE is belonging to */
   THD	*in_use;                        /* Which thread uses this */
   Field **field;			/* Pointer to fields */
 
diff --git a/sql/table_cache.cc b/sql/table_cache.cc
index d635d1b..8ab1fae 100644
--- a/sql/table_cache.cc
+++ b/sql/table_cache.cc
@@ -56,6 +56,8 @@
 ulong tdc_size; /**< Table definition cache threshold for LRU eviction. */
 ulong tc_size; /**< Table cache threshold for LRU eviction. */
 ulong tc_instances;
+static uint32 tc_active_instances= 1;
+static uint32 tc_contention_warning_reported;
 
 /** Data collections. */
 static LF_HASH tdc_hash; /**< Collection of TABLE_SHARE objects. */
@@ -127,10 +129,12 @@ struct Table_cache_instance
             I_P_List_null_counter, I_P_List_fast_push_back<TABLE> >
     free_tables;
   ulong records;
+  uint mutex_waits;
+  uint mutex_nowaits;
   /** Avoid false sharing between instances */
   char pad[CPU_LEVEL1_DCACHE_LINESIZE];
 
-  Table_cache_instance(): records(0)
+  Table_cache_instance(): records(0), mutex_waits(0), mutex_nowaits(0)
   {
     mysql_mutex_init(key_LOCK_table_cache, &LOCK_table_cache,
                      MY_MUTEX_INIT_FAST);
@@ -142,6 +146,50 @@ struct Table_cache_instance
     DBUG_ASSERT(free_tables.is_empty());
     DBUG_ASSERT(records == 0);
   }
+
+  void lock_and_check_contention(uint32 n_instances)
+  {
+    if (mysql_mutex_trylock(&LOCK_table_cache))
+    {
+      mysql_mutex_lock(&LOCK_table_cache);
+      if (++mutex_waits == 500)
+      {
+        if (n_instances < tc_instances)
+        {
+          if (my_atomic_cas32_weak_explicit(&tc_active_instances, &n_instances,
+                                            n_instances + 1,
+                                            MY_MEMORY_ORDER_RELAXED,
+                                            MY_MEMORY_ORDER_RELAXED))
+          {
+            sql_print_information("Detected contention on table cache mutex: "
+                                  "%d%% waits. Additional table cache instance "
+                                  "activated. Number of instances after "
+                                  "activation: %d.",
+                                  mutex_waits * 100 / (mutex_nowaits + mutex_waits),
+                                  n_instances + 1);
+          }
+        }
+        else if (!my_atomic_fas32_explicit(&tc_contention_warning_reported, 1,
+                                           MY_MEMORY_ORDER_RELAXED))
+        {
+          sql_print_warning("Detected contention on table cache mutex: "
+                            "%d%% waits. Additional table cache instance "
+                            "cannot be activated: consider raising "
+                            "table_open_cache_instances. Number of active "
+                            "instances: %d.",
+                            mutex_waits * 100 / (mutex_nowaits + mutex_waits),
+                            n_instances);
+        }
+        mutex_waits= 0;
+        mutex_nowaits= 0;
+      }
+    }
+    else if (++mutex_nowaits == 1000)
+    {
+      mutex_waits= 0;
+      mutex_nowaits= 0;
+    }
+  }
 };
 
 
@@ -287,11 +335,12 @@ void tc_purge(bool mark_flushed)
 
 void tc_add_table(THD *thd, TABLE *table)
 {
-  ulong i= thd->thread_id % tc_instances;
+  uint32 i= thd->thread_id % my_atomic_load32_explicit(&tc_active_instances, MY_MEMORY_ORDER_RELAXED);
   TABLE *LRU_table= 0;
   TDC_element *element= table->s->tdc;
 
   DBUG_ASSERT(table->in_use == thd);
+  table->instance= i;
   mysql_mutex_lock(&element->LOCK_table_share);
   /* Wait for MDL deadlock detector to complete traversing tdc.all_tables. */
   while (element->all_tables_refs)
@@ -327,10 +376,12 @@ void tc_add_table(THD *thd, TABLE *table)
 
 static TABLE *tc_acquire_table(THD *thd, TDC_element *element)
 {
-  ulong i= thd->thread_id % tc_instances;
+  uint32 n_instances=
+    my_atomic_load32_explicit(&tc_active_instances, MY_MEMORY_ORDER_RELAXED);
+  uint32 i= thd->thread_id % n_instances;
   TABLE *table;
 
-  mysql_mutex_lock(&tc[i].LOCK_table_cache);
+  tc[i].lock_and_check_contention(n_instances);
   table= element->free_tables[i].list.pop_front();
   if (table)
   {
@@ -375,7 +426,7 @@ static TABLE *tc_acquire_table(THD *thd, TDC_element *element)
 
 void tc_release_table(TABLE *table)
 {
-  ulong i= table->in_use->thread_id % tc_instances;
+  uint32 i= table->instance;
   DBUG_ASSERT(table->in_use);
   DBUG_ASSERT(table->file);
 


More information about the commits mailing list