数据库内核月报 - 2015 / 08-MySQL · 功能分析 · MySQL表定义缓存

本文涉及的产品
云数据库 RDS SQL Server,基础系列 2核4GB
RDS PostgreSQL Serverless,0.5-4RCU 50GB 3个月
推荐场景:
对影评进行热评分析
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
简介:

表定义

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链表呢?
    1. 系统表,如sys_tables sys_columns sys_fields SYS_INDEXES等;
    2. 有引用关系的表都加入table_non_LRU(dict_foreign_add_to_cache);
    3. 有全文索引的表都加入table_non_LRU(fts_optimize_add_table);
    4. 便于删表,删表前对将表加入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_namedict_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)。

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

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
27天前
|
存储 缓存 数据库
解决缓存与数据库的数据一致性问题的终极指南
解决缓存与数据库的数据一致性问题的终极指南
118 63
|
2月前
|
消息中间件 canal 缓存
项目实战:一步步实现高效缓存与数据库的数据一致性方案
Hello,大家好!我是热爱分享技术的小米。今天探讨在个人项目中如何保证数据一致性,尤其是在缓存与数据库同步时面临的挑战。文中介绍了常见的CacheAside模式,以及结合消息队列和请求串行化的方法,确保数据一致性。通过不同方案的分析,希望能给大家带来启发。如果你对这些技术感兴趣,欢迎关注我的微信公众号“软件求生”,获取更多技术干货!
115 6
项目实战:一步步实现高效缓存与数据库的数据一致性方案
|
2月前
|
canal 缓存 NoSQL
Redis缓存与数据库如何保证一致性?同步删除+延时双删+异步监听+多重保障方案
根据对一致性的要求程度,提出多种解决方案:同步删除、同步删除+可靠消息、延时双删、异步监听+可靠消息、多重保障方案
Redis缓存与数据库如何保证一致性?同步删除+延时双删+异步监听+多重保障方案
|
3月前
|
消息中间件 缓存 监控
如何保证缓存和数据库的一致性?
保证缓存和数据库的一致性的做法
|
12天前
|
缓存 弹性计算 NoSQL
新一期陪跑班开课啦!阿里云专家手把手带你体验高并发下利用云数据库缓存实现极速响应
新一期陪跑班开课啦!阿里云专家手把手带你体验高并发下利用云数据库缓存实现极速响应
|
25天前
|
存储 缓存 API
LangChain-18 Caching 将回答内容进行缓存 可在内存中或数据库中持久化缓存
LangChain-18 Caching 将回答内容进行缓存 可在内存中或数据库中持久化缓存
38 6
|
2月前
|
消息中间件 缓存 NoSQL
15)如何保证缓存和数据库之间的数据一致性
15)如何保证缓存和数据库之间的数据一致性
52 1
|
2月前
|
SQL 存储 关系型数据库
mysql-视图的定义和简单使用
这篇文章介绍了MySQL中视图的定义和简单使用方法,包括视图的创建规则和使用限制。通过一个实际的例子,展示了如何创建视图以及如何使用视图来简化复杂的SQL查询操作。
mysql-视图的定义和简单使用
|
3月前
|
存储 消息中间件 人工智能
AI大模型独角兽 MiniMax 基于阿里云数据库 SelectDB 版内核 Apache Doris 升级日志系统,PB 数据秒级查询响应
早期 MiniMax 基于 Grafana Loki 构建了日志系统,在资源消耗、写入性能及系统稳定性上都面临巨大的挑战。为此 MiniMax 开始寻找全新的日志系统方案,并基于阿里云数据库 SelectDB 版内核 Apache Doris 升级了日志系统,新系统已接入 MiniMax 内部所有业务线日志数据,数据规模为 PB 级, 整体可用性达到 99.9% 以上,10 亿级日志数据的检索速度可实现秒级响应。
AI大模型独角兽 MiniMax 基于阿里云数据库 SelectDB 版内核 Apache Doris 升级日志系统,PB 数据秒级查询响应
|
3月前
|
存储 SQL 监控
ADBPG&Greenplum成本优化问题之ADB PG的数据库管控的定义如何解决
ADBPG&Greenplum成本优化问题之ADB PG的数据库管控的定义如何解决
42 2

相关产品

  • 云数据库 RDS MySQL 版