mysql 5.1 table cache
table cache包含table open cache和table definition cache,都由server层管理
table_open_cache: 内存中缓存的打开的表的TABLE实例数目,线程之间独立,一个表可以被多个线程同时打开从而在table cache中可以有多个实例
table_definition_cache:内存中缓存打开的表的TABLE_SHARE实例数目,一个share在table cache中只有一个实例
mysql 5.1使用open_cache(HASH)管理table cache,每个TABLE实例中包含一个TABLE_SHARE指针成员s,它在不同的TABLE实例间共享,s内部有一个引用计数单元,记录了table cache中引用s的TABLE实例个数
当有引用s的TABLE实例被释放,其引用计数减1,如果s的引用计数减为0,且此时table_def_cache.records > table_def_size时,s也会被释放掉,TABLE_SHARE被table_def_cache(HASH)维护
5.1.25之后,table_definition_cache:默认和最小都是256
query/dml引起的table cache管理
free_cache_entry:从table cache中删除一个TABLE实例
table_def_free_entry:从table_def_cache中删除一个TABLE_SHARE实例
query/dml执行过程中调用open_tables,close_thread_tables等函数时会对table cache进行维护
- mysql_execute_command
- ...................
- |->open_tables
- |->open_table
- ...................
- ...execute query...
- ...................
- |->close_thread_tables
何时释放TABLE?
1、close_cached_tables,如FLUSH TABLES
2、open_table,当需要新建一个TABLE实例,即未在table cache中找到空闲的TABLE,会做检查,当open_cache.records > table_cache_size时,unused_tables(TABLE链表)会被释放,直到open_cache.records <= table_cache_size,调用流程如下:
- hash_delete(&open_cache,(uchar*) unused_tables)
- free_cache_entry
- |->intern_close_table
- |->closefrm
- |->release_table_share
release_table_share中会对table_def_cache.records进行检查,如果其值超过table_def_size且其引用计数为0,table share也被释放
在closefrm中,TABLE实例中的handler指针file被释放,会调用一系列存储引擎的函数,相应的,在新分配一个TABLE实例时,会初始化file指针,调用get_new_handler,file->open等函数,这些操作有一定的代价,应该减少
释放的TABLE是位于unused_tables中,否则table cache将自动扩展,暂时不释放
何时释放TABLE_SHARE?
1、get_table_share(在open_table中被open_unireg_entry调用),会进行检查,当table_def_cache.records > table_def_size时,oldest_unused_shares(TABLE_SHARE链表)会被释放,直到table_def_cache.records <= table_def_size,调用流程如下:
- my_hash_delete(&table_def_cache, (uchar*) oldest_unused_share);
- table_def_free_entry
- |->free_table_share
2、close_cached_tables,如执行FLUSH TABLES
3、释放TABLE时,引用计数减为0且table_def_cache大小超过table_def_size
释放TABLE_SHARE时,其ref_count为0,如果ref_count不为0,table_def_cache被扩展,在以后当ref_count为0时被释放
table cache LRU 管理
当一个query/dml结束后,会将thd使用的表放回空闲链表中,代码调用:
- mysql_execute_command
- |->close_thread_tables
- |->close_open_tables
- |->close_thread_table
TABLE_SHARE的释放采用LRU顺序,由oldest_unused_share,end_of_unused_share这两个链表指针控制实现:空闲的SHARE是插入到end_of_unused_share之前,即尾插法,而释放时是从链表的头部oldest_unused_share开始的,代码详见release_table_share和table_def_init函数
空闲TABLE实例的释放也采用LRU顺序,TABLE空闲时被移到unused_tables中是插在链表的尾部,释放时也是从unused_tales头部开始,整个unused_tables是一个环形的双链表,代码详见close_thread_table和free_cache_entry函数
mysql 5.5 table cache
table_definition_cache:默认和最小都是400
5.1中table cache的open_cache(HASH)已经不使用了,而是在TABLE_SHARE中增加了两个链表used_tables和free_tables,用以管理该表上打开的TABLE实例
TABLE_SHARE结构体中的几个变量:
- struct TABLE_SHARE
- {
- ...
- TABLE_SHARE *next, **prev; /* Link to unused shares */
- /* prev为二级指针,保存的是指向自己的指针(前一个节点的next指针)的地址 */
- /*
- Doubly-linked (back-linked) lists of used and unused TABLE objects
- for this share.
- */
- I_P_List <TABLE, TABLE_share> used_tables;
- I_P_List <TABLE, TABLE_share> free_tables;
- ...
- }
本质上,5.1和5.5在table cache的管理上没有很大区别,搜索的效率是一样的,5.5通过table_def_cache先找到TABLE_SHARE,后在free_tables链表中找空闲的TABLE,而5.1直接在open_cache中搜索没有被使用的TABLE。
对于table_def_cache,只要设置不低于数据库中表的个数就行了,而对于table_open_cache和MySQL运行时的并发数有关,如果系统并发连接比较多应当适当设置大些
阅读(4958) | 评论(0) | 转发(0) |