Home > Database > Mysql Tutorial > body text

改进MySQL的table_cache

WBOY
Release: 2016-06-07 17:07:26
Original
967 people have browsed it

改进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.

source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
About us Disclaimer Sitemap
php.cn:Public welfare online PHP training,Help PHP learners grow quickly!