MySQL表定义缓存
表定义
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链表链接。
获取TABLE_SHARE(
get_table_share) 先从HASH查找,找不到再读取frm文件加载表定义信息。同时递增引用计数。释放TABLE_SHARE(
release_table_share) 递减引用计数。当引用计数为0时,如果版本发生变化,直接删除此TABLE_SHARE。
old_unused_share链表调整:
获取TABLE_SHARE时(
get_table_share) 未使用的TABLE_SHARE对象被启用,须从LRU链表取出; 如果缓存总数超出table_definition_cache大小,须依次从old_unused_share链表尾部去除。释放TABLE_SHARE时(
release_table_share) 当引用计数为0时,如果版本没有发生变化,将TABLE_SHARE对象加入old_unused_share链表尾部。如果缓存总数超出table_definition_cache大小,须依次从old_unused_share链表尾部去除。 真正free TABLE_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链表组成。
两个hash表,分别按name和id,便于按name和id进行查找。
table_non_LRU: 存放不放入到LRU链表的表,这些表不会从缓存中淘汰出去。那么哪些表会放入table_non_LRU链表呢?
- 系统表,如sys_tables sys_columns sys_fields SYS_INDEXES等;
- 有引用关系的表都加入table_non_LRU(dict_foreign_add_to_cache);
- 有全文索引的表都加入table_non_LRU(fts_optimize_add_table);
- 便于删表,删表前对将表加入table_non_LRU,删表时加载表时保证表仍然在缓存中,例如表corrupted时。
table_LRU 不在table_non_LRU链表中的表都加入table_LRU链表中。
dict_table_t* sys_tables 等 常用系统表单独标识出来,每次使用时直接取出,不需要从hash表查找。
LRU的维护 既然存在table_LRU链表,我们就需要考虑LRU的调整:
1. 将最近使用的表放入LRU头部(`dict_move_to_mru`)
每次按name和id查找时都会调整,参考`dict_table_open_on_name`和`dict_table_open_on_id`。
2. LRU的淘汰
* 淘汰哪些表
LRU中表才可以淘汰,table\_non\_LRU中的表不参入淘汰。
表引用计数必须为0(`table->n_ref_count == 0`)。
表的索引被自适应哈希引用计数必须为0(`btr_search_t->ref_count=0`)。
* 何时淘汰
主线程控制每47(SRV\_MASTER\_DICT\_LRU\_INTERVAL)秒检查一次,只遍历一半LRU链表。
主线程空闲时检查一次,但扫所有LRU链表,清理控制缓存表个数不能超过table\_definition\_cache。
* 如何淘汰
从LRU尾部开始,淘汰满足条件表(`dict_make_room_in_cache`)。
注:
- table_non_LRU没有实际作用,主要用于debug;
- 如果有较多引用约束的表,它们不受LRU管理,参数table_definition_cache的作用会弱化。
MySQL表定义缓存的更多相关文章
- redmine 自己定义字段mysql表结构
redmine能够创建自己定义字段,我经经常使用它来满足不同的管理需求.如今来解读一下.看看这些自己定义字段是怎样存在mysql表中的. 表issues 用来存放issue的标准字段. mysql&g ...
- MySQL的表定义语法
表定义 只有成功创建数据库后,才能创建数据表,数据表是字段的集合,在表中数据按行和列的格式存储 创建表 MySQL 使用 CREATE TABLE 创建表.其中有多个选择,主要由表创建定义(creat ...
- MySQL表的操作
一.存储引擎(了解) 前几节我们知道mysql中建立的库===>文件夹,库中的表====>文件 现实生活中我们用来存储数据的文件有不同的类型,每种文件类型对应各自不同的处理机制:比如处理文 ...
- 查询优化百万条数据量的MySQL表
转自https://www.cnblogs.com/llzhang123/p/9239682.html 1.两种查询引擎查询速度(myIsam 引擎 ) InnoDB 中不保存表的具体行数,也就是说, ...
- java面试题之----mysql表优化方案
本文转载自segmentfault,原文链接:https://segmentfault.com/a/1190000006158186. 当MySQL单表记录数过大时,增删改查性能都会急剧下降,可以参考 ...
- mysql————表类型(存储引擎)的选择
表类型(存储引擎)的选择 7.1 mysql存储引擎概述 插件式存储引擎是mysql数据库最重要的特性之一,用户可以根据应用的需要选择ruhr存储和索引数据,是否使用事务等. InnoDB和BDB提供 ...
- MySQL表的四种分区类型
MySQL表的四种分区类型 一.什么是表分区 通俗地讲表分区是将一大表,根据条件分割成若干个小表.mysql5.1开始支持数据表分区了. 如:某用户表的记录超过了600万条,那么就可以根据入库日期将表 ...
- MySQL 表分区详解MyiSam引擎和InnoDb 区别(实测)
一.什么是表分区通俗地讲表分区是将一大表,根据条件分割成若干个小表.mysql5.1开始支持数据表分区了.如:某用户表的记录超过了1000万条,那么就可以根据入库日期将表分区,也可以根据所在地将表分区 ...
- 使用redis和fastjson做应用和mysql之间的缓存
第一次做这种javaweb的项目,难免还是要犯很多错误. 大概也知道,redis常常被用来做应用和mysql之间的缓存.模型大概是这样子的. 为了让redis能够缓存mysql数据库中的数据,我写了很 ...
随机推荐
- 关于php跨域cookie共享使用方法
A 服务器所在的域:a1.main.com,A 有应用 main.phpB 服务所在的域:b1.test.com,B 有应用 test.php 1.在 main.php 里设置 cookie 的时候, ...
- NHibernate系列文章十一:NHibernate并发控制
摘要 在同一时刻数据访问量和更新次数比较大的系统中,产生了数据的并发访问问题.并发访问使得在这样的环境中,所有用户(程序.实际用户.进程.线程等)的操作不产生负面问题. 如果不使用并发,在两个用户同时 ...
- NHibernate系列文章十八:NHibernate关系之一对多(附程序下载)
摘要 这篇文章介绍NHibernate最实用的内容:关系映射. NHibernate的关系映射方式有三种: Set:无序对象集合,集合中每一个元素不能重复. List:有序对象集合,集合中的元素可以重 ...
- 轻量数据交换json,xml,ini
json语法: object {string:value,...} value string/number/object/array/true/false/null array value ...
- 问题Initial SessionFactory creation failed.org.hibernate.HibernateException: /hibernate.cfg.xml not found解决方法
问题Initial SessionFactory creation failed.org.hibernate.HibernateException: /hibernate.cfg.xml not fo ...
- js常用正则表达式2
字符 含意 \ 做为转意,即通常在"\"后面的字符不按原来意义解释,如/b/匹配字符"b",当b前面加了反斜杆后/\b/,转意为匹配一个单词的边界. -或- 对 ...
- (转载)IOS中UIScrollView的属性和委托方法
http://www.jizhishusheng.com/?p=453 ---- 以下内容来自 UIScrollView 类负责所有基于 UIKit 的滚动操作一.创建 1. CGRect bou ...
- 构建ASP.NET网站十大必备工具(2)
正常运行时间 当一个网站发布以后,你肯定希望你的网站不会遇到任何问题,一直处在正常运行状态之中.现在,我使用下面这些工具来监控“Superexpert.com”网站,确保它一直处在正常运行状态之中. ...
- css 层的嵌套
html <div class="menu"> <ul> <li><a class="li1" title=" ...
- JS控制鼠标点击事件
鼠标点击事件就是当鼠标点击元素时,就会出现另一个窗口,类似于百度首页中右上角的“登录”这个按钮,当鼠标点击 登录时,就会出现登录窗口.大体的意思就是这样,直接上代码了,简单易懂. <!DOCTY ...