mysql数字字典相关(5.6、5.7)

 

目录

table_cache

table_cache的使用背景

table_cache的存储结构

table_cache_element

Table

Table_Share

Innodb(innobase_share)

参考链接


table_cache

table_cache的使用背景

当我们的客户端程序提交 Query 给 MySQL 的时候,MySQL 需要对 Query 所涉及到的每一个表都取得一个表文件句柄信息,如果没有 Table Cache,那么 MySQL 就不得不频繁的进行打开关闭文件操作,无疑会对系统性能产生一定的影响,Table Cache 正是为了解决这一问题而产生的。在有了 Table Cache 之后,MySQL 每次需要获取某个表文件的句柄信息的时候,首先会到 Table Cache 中查找是否存在空闲状态的表文件句柄。如果有,则取出直接使用,没有的话就只能进行打开文件操作获得文件句柄信息。在使用完之后,MySQL 会将该文件句柄信息再放回 Table Cache 池中,以供其他线程使用。

对于每个连接线程,访问一张表时,每个线程都有自己本地的table cache,这样可以避免每次访问全局的table definetion cache来获得table的元数据,以免多线程并发访问时产生锁等待,但是缺点是增加了一定的内存开销。另外,每个table cache元素,除了有sql层TABLE_SHARE的内容外,还有对应storage层的handler,不同存储引擎对应的handler不同,表示该表在存储层需要使用对应的存储引擎进行操作。

table_cache的存储结构

table_cache是一个hash表结构,hash的元素是table_cache_element。

即某一个表在某个table_cache中存储的是一个table_cache_element,然后如果使用的话,还要到空闲链表中去查找。

table_cache_element

这个元素里面重要的是有两个链表,进行这个表在server层的缓存。每个链表的元素是Table,定义见下面。

table定义里面重要的结构体是有指向table share的指针,也有指向具体存储引擎的handler指针。

class Table_cache_element
{
private:
  /*
    Doubly-linked (back-linked) lists of used and unused TABLE objects
    for this table in this table cache (one such list per table cache).
  */
  typedef I_P_List <TABLE,
                    I_P_List_adapter<TABLE,
                                     &TABLE::cache_next,
                                     &TABLE::cache_prev> > TABLE_list;

  TABLE_list used_tables;
  TABLE_list free_tables;
  TABLE_SHARE *share;

public:

  Table_cache_element(TABLE_SHARE *share_arg)
    : share(share_arg)
  {
  }

  TABLE_SHARE * get_share() const { return share; };

  friend class Table_cache;
  friend class Table_cache_manager;
  friend class Table_cache_iterator;
};

Table

struct TABLE
{
  TABLE() {}                               /* Remove gcc warning */
  /*
    Since TABLE instances are often cleared using memset(), do not
    add virtual members and do not inherit from TABLE.
    Otherwise memset() will start overwriting the vtable pointer.
  */

  TABLE_SHARE    *s;
  handler    *file;
  TABLE *next, *prev;
......
}

Table_Share

MySQL对一张表的定义建的对象, table_def_cache参数控制缓存的对象就是table_share;

里面存储的内容主要来自于.frm文件(.frm是mysql sql层的表的元数据信息,主要存储了表结构的定义),相当于.frm文件的缓存。同时,一个table的不同table object会share一个TABLE_SHARE。

table_share的管理:

TABLE_SHARE使用hash表进行快速查找,数据库名和table名作为其key,对应的名字是table_def_cache,TABLE_SHARE有大小限制,由table_definition_cache决定,因此,TABLE_SHARE使用LRU进行管理,对应的链表名字时oldest_unused_share

1、查找使用:当用户有对表t1的查询请求时:1)在其本地的查找有无对应的table_cache元素,2)如果没有,调用get_table_share则到全局的table definition cache中查找有无对应的TABLE_SHARE,3)如果还没有,则从本地的t1表对应的t1.frm读取对TABLE_SHARE进行初始化,并插入到全局的table_def_cache中,并增加其引用计数。4)读取到TABLE_SHARE,对应的客户线程会将其缓存在table_cache,方便下次访问直接使用。

注意:1)如果TABLE_SHARE在第1步中找到,并且其在oldest_unused_share中,则需要将其从oldest_unused_share移除;2)如果读取TABLE_SHARE的个数超过了table_def_cache的大小,需要从oldest_unused_share链表的尾部将其它表TABLE_SHARE从table_def_cache中删除。

2、删除失效:当用户进行DDL操作时,会改变表的定义(也即TABLE_SHARE中的版本号会改变),也即会修改.frm文件。因此,对于.frm文件的缓存TABLE_SHARE,也需要在DDL时进行失效。因此会调用release_table_share,将表的TABLE_SHARE从table_def_cache和oldest_unused_share中删除。当然,有时候一些操作如close table会调用release_table_share,来减少表对应的TABLE_SHARE的引用计数,如果引用计数为0了,但是版本没发生变化,则将其放入到TABLE_SHARE尾部,并且不会将其从table_def_cache中删除。下次,如果在使用该表,则无需磁盘上读取。

 

Innodb(innobase_share)

innobase_share是innodb层对某张表的定义,全局共享结构, 受 innobase_share_mutex保护。
innobase_open_tables 是一个hash表,保存着所有的INNOBASE_SHARE。

存储引擎的表定义缓存,如果没有的话,需要从系统表中打开这个表
dict_sys->table_hash。
dict_sys_t:整个系统的数据字典, 全局的 dict_sys_t* dict_sys;
      包括:hash_table_t* table_hash; /*!< hash table of the tables, based
      包括:UT_LIST_BASE_NODE_T(dict_table_t) table_LRU; /*!< LRU list of tables */
数组字典使用了两个结构存储,一个hash方便查询, 一个是lru链表,用于缓存的置换。

参考链接

https://zhuanlan.zhihu.com/p/39256558

https://developer.aliyun.com/article/50961

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值