改进MySQL的table_cache

WBOY
發布: 2016-06-07 17:07:26
原創
966 人瀏覽過

改进MySQL的table_cache,在mysql里面有一个参数table_cache,当设置过大时,会产生明显的效率下降。这是因为扫描open_cache哈希

在mysql里面有一个参数table_cache,当设置过大时,会产生明显的效率下降。这是因为扫描open_cache哈希表时,使用的线性扫描,时间复杂度为O(n),mysql的bug list上有人提供了一个patch(?id=33948),可以把时间降到o(1),其基本思想是为table实例增加三个指针,来维护一个空闲链表。

首先,我们分析一下mysql在打开一个表时如何工作:

在mysql里,table_cache是一个比较重要的参数。由于多线程机制,每个线程独自打开自己需要的标的文件描述符,而不是共享已经打开的。


1. table_cache key (见create_table_def_key)

在内存里,table cache使用hash表来存储,key为  database_name\0table_name\0+(可选的,,用于临时表)


这里对于临时表会做特殊处理,需要增加额外的信息来保证临时表在slave端是唯一的

增加8个字节:前4个字节为master thread id,后4个字节为slavb


2.打开表时候的处理:open_table


***************

必要的检查:线程栈是否足够,thd是否被kill

**************

全局锁:lock_open

*************************

首先判断是否是临时表

*************************

这里有一段很有意思的逻辑,当需要打开表时,总是先从临时表链表中查找表。也就是说,当存在一个与实际表同名的临时表时,会总是操作临时表

if (!table_list->skip_temporary)
  {
    for (table= thd->temporary_tables; table ; table=table->next)
    {


**********************************************

非临时表,且处于pre-locked 或 lock_tables mode(thd->locked_tables || thd->prelocked_mode)

即该线程已经打开或锁定了一些表,从thd->open_tables里查询,当不存在时,返回error

**********************************************

if (thd->locked_tables || thd->prelocked_mode)
  {                              // Using table locks
    TABLE *best_table= 0;
    int best_distance= INT_MIN;
    for (table=thd->open_tables; table ; table=table->next)
    {


*******************************************************

正常情况:

1. 首先尝试从table cache中取table

2. 当找到的TABLE实例是nam-locked的,或者一些线程正在flush tables,我们需要等待,直到锁释放

3. 如果不存在这样的TABLE,我们需要创建TABLE,并将其加入到cache中

!这些操作都需要全局锁:LOCK_open,来保护table cache和磁盘上的表定义

*******************************************************


如果这是该query打开的第一个表:设置thd->version = refresh_version,这样,当我们打开剩余表的过程中,如果 version发生了变化,则需要back off,关闭所有已经打开的并重新打开表

目前refresh_version只会被FLUSH TABLES命令改变


 if (thd->handler_tables)         
    mysql_ha_flush(thd);   //刷新(关闭并标记为re-open)所有需要reopen的表



查询table cache的过程:


 for (table= (TABLE*) hash_first(&open_cache, (uchar*) key, key_length,                  //基于同一个key来查找hash表
                                  &state);
       table && table->in_use ;
       table= (TABLE*) hash_next(&open_cache, (uchar*) key, key_length,
                                 &state))

{

     


**********************************

flush tables marked for flush.

來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
最新問題
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!