改进MySQL的table_cache
以下为本人在工作中的碎碎念,记录的比较凌乱……
........................................................................
在mysql里面有一个参数table_cache,当设置过大时,会产生明显的效率下降。这是因为扫描open_cache哈希表时,使用的线性扫描,时间复杂度为O(n),mysql的bug list上有人提供了一个patch(http://bugs.mysql.com/bug.php?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和磁盘上的表定义
*******************************************************
相关新闻>>
- 发表评论
-
- 最新评论 更多>>