MYSQL表对象的字典缓存
2012-05-13 12:08:28 来源:WEB开发网核心提示: 在MYSQL中,同样有很多类型的系统对象,MYSQL表对象的字典缓存,包括表、视图、存储过程、存储函数等,但由于MYSQL的插件式存储引擎及其它实现方面的特点,真正与用户交互的是TABLE_SHARE的一个衍生品,它对应的结构体名字为TABLE,其每一种对象的缓存方式都不同,或者说这些对象的缓存不是通过一种统一的方
在MYSQL中,同样有很多类型的系统对象,包括表、视图、存储过程、存储函数等,但由于MYSQL的插件式存储引擎及其它实现方面的特点,其每一种对象的缓存方式都不同,或者说这些对象的缓存不是通过一种统一的方式来管理的,每一种对象的缓存都是有自己的特点,并且缓存的内容也有很大的差异,下面先只叙述一下表对象的缓存方式。
表字典对象缓存,顾名思义,是将某个表对象的字典信息(定义内容)缓存到内存中,用来提高对表访问的效率。在某一个表第一次被访问过之后,在服务器没有关闭并且表定义没有被修改的条件下,访问这个表时,只需要从内存中找到这个已经缓存起来的对象并且做相应操作即可,而不需要再次从系统表中读取它的定义并且解析,然后再做相应的操作。
当某一个用户要查询某一个表的数据时,系统首先会找到这个表。上面已经提到过,因为MYSQL实现了表的缓存,所以首先会从缓存中寻找这个表,表字典对象的缓存是通过HASH表来管理的,MYSQL系统中,专门有一个HASH表(源代码中的名字是table_def_cache)用来存储组织表对象。
所以首先通过表的名字(包括了模式名)来构造一个HASH键值(KEY),用来从HASH表中搜索对象。
但是对于表对象的缓存,不只是简单的将一些表的定义通过HASH存储起来就算完了,那这样的话缓存可能没有任何意义,或者说局限性非常大,这样可能导致一个用户在表对象上做了什么标志或者修改等都会影响到其它用户,这种影响是不可预期的,更重要的原因是,MYSQL是插件式的数据库,每一个用户得到表对象之后还需要将表实例化,这个实例化的对象只有自己才能使用,所以不是简单的所有用户都使用同一个缓存对象即可完成的。它的缓存其实是用了一种可以称为“共享私有化缓存”,看上去这个说法是矛盾的,其实并不是这样的,它在缓存过程中用到一个叫TABLE_SHARE的结构体,一个这个结构体唯一对应MYSQL中的一个表对象,这里是不区分任何存储引擎的,它实际上就是对具体一个表的定义的翻译或映射,也就是说当需要打开一个表的时候,这个表首先是在MYSQL的系统表中存储的(当然系统表是分不同的存储引擎的,不同的存储引擎有自己的系统表,这里所说的MYSQL的系统表应该是一种统称,其实是具体某一个存储引擎的系统表),如果要使用了,首先需要从系统表中将这个表的所有信息都读入到内存中来,这些信息包括表名、模式名、所有的列信息、列的默认值、表的字符集、对应的frm文件的路径、所属的存储引引擎(MYSQL中的表可以单独定义自己的存储引擎)、主键等等,当然还有很多其它信息,所有这些信息读入内存中的时候首先就是通过结构体TABLE_SHARE来存储的,相当于这个结构体是一个表对象缓存的第一层,同时从名字就可以看出,这个结构体是所以用户都可以共享的一个表对象,所以它是静态的,不允许修改的(内存中),从系统表中读取进来之后直到这个表从缓存中删除,中间不会做任何的修改。
那么用户要访问一个表,只是构造了TABLE_SHARE是远远不够的,而且这个结构体对象也不是直接给用户使用的对象,在构造了这个结构体之后,首先需要将其缓存起来,因为这个结构体就是我们这里讨论的核心,它就是我们要缓存的对象,所以首先需要根据上面计算得到的KEY将这个表对象缓存到table_def_cache中,这个缓存操作到这里就结束了。
但是如果这个问之前已经被访问过了,那么就不需要再像上面一样构造这个共享结构体了,而是直接通过HASH的KEY值在table_def_cache中找到这个共享结构体即可。
从上面的叙述中知道,当系统得到一个SHARE对象之后,系统会真正的构造一个新的对象交给当前的操作,这个对象上面已经说过了,肯定不是TABLE_SHARE,因为这个是缓存对象,它是静态的,只读的,真正与用户交互的是TABLE_SHARE的一个衍生品,它对应的结构体名字为TABLE,它是真正的在操作中被使用的对象,那么是如何从TABLE_SHARE变为TABLE的呢?
更多精彩
赞助商链接