数据库内核月报

数据库内核月报 - 2015 / 08

MySQL · 功能分析 · MySQL表定义缓存

Author: 济天

表定义

MySQL的表包含表名,表空间、索引、列、约束等信息,这些表的元数据我们暂且称为表定义信息。 对于InnoDB来说,MySQL在server层和engine层都有表定义信息。server层的表定义记录在frm文件中,而InnoDB层的表定义信息存储在InnoDB系统表中。例如:

 InnoDB_SYS_DATAFILES   
 InnoDB_SYS_TABLESTATS  
 InnoDB_SYS_INDEXES     
 InnoDB_SYS_FIELDS      
 InnoDB_SYS_TABLESPACES 
 InnoDB_SYS_FOREIGN_COLS
 InnoDB_SYS_FOREIGN     
 InnoDB_SYS_TABLES      
 InnoDB_SYS_COLUMNS     

注:以上都是memory表,它们内容是从实际系统表中获取的。实际上InnoDB系统表engine也是InnoDB类型的,数据也是以B树组织的。

在数据库每次执行sql都会访问表定义信息,如果每次都从frm文件或系统表中获取,效率会较低。因此MySQL在server层和InnoDB层都有表定义的缓存。以MySQL 5.6为例,参数table_definition_cache控制了表定义缓存中表的个数,server层和InnoDB层的表定义缓存共用此参数。

server层表定义缓存

server层表定义为TABLE_SHARE对象,TABLE_SHARE对象有引用计数和版本信息,每次使用flush操作会递增版本信息。 server层表定义缓存由hash表和old_unused_share链表组成,通过hash表table_def_cache以表名为key缓存TABLE_SHARE对象,同时未使用的TABLE_SHARE对象通过old_unused_share链表链接。

old_unused_share链表调整:

InnoDB层表定义缓存

InnoDB表定义为dict_table_t, 缓存为dict_sys_t,结构如下

struct dict_sys_t{
    ...
    hash_table_t*    table_hash;    /*!< hash table of the tables, based
                    on name */
    hash_table_t*    table_id_hash;    /*!< hash table of the tables, based
                    on id */
    ulint        size;        /*!< varying space in bytes occupied
                    by the data dictionary table and
                    index objects */
    dict_table_t*    sys_tables;    /*!< SYS_TABLES table */
    dict_table_t*    sys_columns;    /*!< SYS_COLUMNS table */
    dict_table_t*    sys_indexes;    /*!< SYS_INDEXES table */
    dict_table_t*    sys_fields;    /*!< SYS_FIELDS table */

    UT_LIST_BASE_NODE_T(dict_table_t)
            table_LRU;    /*!< List of tables that can be evicted
                    from the cache */
    UT_LIST_BASE_NODE_T(dict_table_t)
            table_non_LRU;    /*!< List of tables that can't be
                    evicted from the cache */
};

主要由hash表和LRU链表组成。

注:

  1. table_non_LRU没有实际作用,主要用于debug;
  2. 如果有较多引用约束的表,它们不受LRU管理,参数table_definition_cache的作用会弱化。