在了解Mysql表缓存之前首先要先对mysql中一条sql的执行流程,看下面的草图可以有一个清晰的认识:

MySQL多级缓存 mysql两级缓存_mysql

表结构的缓存,二级表对象的缓存。

一级表结构缓存:

查询的话,首先是找到表,由于第一次访问这个表,缓存里面没有。那么就会从System表里面去找,mysql元数据里面有每个表的定义,包括列信息、存储引擎、主键等等都有,找到这小子之后,就会构建出一个TABLE_SHARE(所有用户共享的)。这个玩意是个静态的,不能修改,完事了加载到内存和缓存中。

二级表对象缓存

虽然上面已经生成了一级表结构缓存,但是还是不能操作这个表,因为还缺少一个详细的对象。

TABLE_SHARE只是包含的一些公共的基础信息,可以理解为一个模板类。在访问的时候每个客户端之间是隔离的,还需要补填一些独有的信息,比如说不同用户对该表的权限等等,所以要想操作这个表,还需要创建一个表对象来供当前客户端(线程)使用。

创建这个表对象也就是实例化的过程,每个用户独享一个实体,我们称这个玩意为table实例。这个table实例里面保存了对TABLE_SHARE的引用,从这里面获取一些表的基础信息,还有一些属性,比如存储引擎的信息也会被初始化(引擎的handler),这个实例对象创建完成之后,它就具备了和存储引擎交互的能力了(通过handler交互),这个实例创建完成之后也会放入缓存中,供下次使用时调用,避免反复创建实例。

mysql层和存储引擎层就是从这开始分家的,table实例就是他们直接沟通的媒介。不同的存储引擎需要提供公共的接口供上层调用(server),并由各自的table实例完成各自的操作。

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

总结:

一共两个缓存,一个是TABLE_SHARE,一个是table实例化缓存。是缓存就会有淘汰策略。第一个缓存在表结构改变时会被删除,或者表居多时也会淘汰。第二个在超出最大值时会淘汰。

有两个参数可以配置table_open_cache和table_definition_cache,一些淘汰策略就是通过这连个参数计算得出的,需要时可以去查一波。

优缺点:

优点:按需加载,不会初始化时全部加载,浪费空间和性能,提高了空间利用率。

缺点:并发情况下可能会实例化多个table实例,导致table_open_cache增长过快,出发淘汰策略。同时如果table比较大,比如有N多个列,那样会占用非常多的内存。