前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >2 mysql底层解析——表对象缓存,包括连接、解析、缓存、引擎、存储等

2 mysql底层解析——表对象缓存,包括连接、解析、缓存、引擎、存储等

作者头像
天涯泪小武
发布2019-08-26 17:41:13
1.3K0
发布2019-08-26 17:41:13
举报
文章被收录于专栏:SpringCloud专栏SpringCloud专栏

学习了mysql的连接层之后,要来看一下mysql的server层了。这一层聚集了mysql的最多的逻辑,包括了请求解析、查询缓存、语义分析、查询优化、各种计算函数、扫描记录、binlog、缓存、锁、内存管理等等。

当一个连接建立起了,用户发过来一个sql语句,从接到这个语句到返回给用户结果,这个过程中,经历了很多事,如果每一步都非常清楚,那么你就能解决大部分的问题。

这一篇主要是讲表对象缓存。

我借用一下别人画的一个图

创建表

假如你已经创建好了一个表,设置好了列、列属性,索引什么的,并且指定好了存储引擎(默认innodb)。

表对象缓存

用户发过来一个sql,譬如select * from tableA where id =1;此时mysql拿到了这个请求,会先到查询缓存中看,之前是不是执行过这个语句。缓存里key就是这个查询语句,如果查询缓存有,那么就直接返回value给客户端。这个查询缓存是个非常鸡肋的东西,新版8.0已经把它删掉了。这里也不多提。

mysql收到请求后,会进行sql语句解析,会分析出,你是查询(插入、删除),哪个表(tableA、tableB),条件。然后先判断sql语句是否合法,假如你写了个selector * 那么就会报错给你看。

ok,要进入正题表对象缓存了。

解析出了表之后,要得到这个表的各种信息。

一级表结构缓存

我要操作表了,首先我要找到这个表。先从缓存中(源码里的table_def_cache,是一个Hash结构)找,根据表名做为Key去找,由于我是第一次访问这个表,缓存里没有。那么就会从System表里去找,熟悉mysql元数据的应该知道,元数据里有每个表的定义,列信息什么的都在表里。找到了这个表,就会构建出这个表的结构体TABLE_SHARE。

这个TABLE_SHARE是一个静态的、不允许修改的(在内存中)结构体TABLE_SHARE,并将其放入缓存中(一个Hash结构里,key就是表名+模式名)。可以理解为一个java里的类,每个字段已经被赋了初始值。这个缓存是属于mysql层的,与后面的存储引擎无关。里面保存了表名、库名、所有列信息、列默认值、表的字符集、对应的frm文件路径、对应的存储引擎、主键等。

请注意,这个结构体就是一级缓存,它被所有用户共享,并且不可修改,从系统表被读入直到该表被修改或删除,这个缓存都会一直存在。

二级表对象缓存

表已经找到了,结构也已经被缓存了,此时我还不能操作这个表。因为缺少一个表对象。

上面的TABLE_SHARE可以理解为一个模板类,包含了表的基本信息,能被所有用户共享。但是里面还缺少一些信息,譬如不同用户对该表的权限、譬如存储引擎信息。那么要想操作这个表,就需要创建一个表对象来供当前用户(线程)使用。

创建表对象就是实例化的过程,每个用户独享一个实例,我们称之为table实例,不会影响其他用户。创建的这个实例,里面有一个指向TABLE_SHARE的引用,用以获取基本信息,还有一些其他属性,譬如存储引擎层的信息也会被初始化(引擎的handler)。

表对象创建完毕后,就具备了和存储引擎交互的能力(通过handler)。创建后,也会放入缓存,供下次使用时避免反复创建实例。

mysql层与存储引擎层,就是从这里开始分家的,table对象就是他俩沟通的桥梁。对于各个存储引擎,需要提供公共的接口来供上层(mysql server)层来调用,并由各自的table实例来完成各自的操作。 譬如插入一条记录,就可以调用table实例中被初始化过的存储引擎的句柄接口函数ha_write_row,进行写入。

这个table实例在一次操作完成之后就不需要了,系统此时并没有将其释放掉,而是保存下来,用一个状态标志位标记一下,并且会调用handler.reset()来重置引擎表状态,目的是handler会被复用,如果不reset,可能导致信息错误。缓存后,当下次用户再访问时,就不需要重新实例化了。

总结

可以看到,当你想操作一个表时,系统对于这个表,会有两层缓存。第一层是SHARE缓存,第二层就是实例化后的对象缓存Table。

是缓存就有淘汰策略,其实我们自己就能判断出来,SHARE缓存只有在表结构定义改变时,才会被删除,但是倘若表巨多,SHARE缓存超出限制,也会淘汰那些不经常使用的SHARE。

第二层的实例缓存,也是有最大值的,超出后则开始淘汰。

涉及的参数变量有两个,table_open_cache和table_definition_cache,一些淘汰策略数值就是靠这两个参数来计算得到的。当你有巨多的表时,可以网上查查这两个参数的涵义,适当调整修改。

优缺点

不同于某些数据库,一启动就加载了所有表信息。mysql是按需加载,由于mysql的插件式存储引擎,mysql做了两层的缓存模型,第二层才加载引擎的handler。

优缺点: 按需加载,提高内存利用率,避免启动时加载所有表信息带来的内存占用。

缺点: 两层缓存带来了效率的损失,每个用户(线程)都要实例化table对象。 在并发情况下,有可能会实例化多个table对象,导致table_open_cache增长过快,导致淘汰掉其他的table对象。同时倘若table比较大,譬如有N多的列,那么会占用非常多的内存。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019年08月21日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 创建表
  • 表对象缓存
    • 一级表结构缓存
      • 二级表对象缓存
        • 总结
          • 优缺点
          相关产品与服务
          对象存储
          对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档