[转帖]mysql中线程缓存并重用的实现机制_MySQL, Oracle及数据库讨论区_Weblogic技术|Tuxedo技术|中间件技术|Oracle论坛|JAVA论坛|Linux/Unix技术|hadoop论坛_联动北方技术论坛  
网站首页 | 关于我们 | 服务中心 | 经验交流 | 公司荣誉 | 成功案例 | 合作伙伴 | 联系我们 |
联动北方-国内领先的云技术服务提供商
»  游客             当前位置:  论坛首页 »  自由讨论区 »  MySQL, Oracle及数据库讨论区 »
总帖数
1
每页帖数
101/1页1
返回列表
0
发起投票  发起投票 发新帖子
查看: 3810 | 回复: 0   主题: [转帖]mysql中线程缓存并重用的实现机制        下一篇 
kim
注册用户
等级:中校
经验:1729
发帖:222
精华:0
注册:2011-7-21
状态:离线
发送短消息息给kim 加好友    发送短消息息给kim 发消息
发表于: IP:您无权察看 2011-8-2 9:19:12 | [全部帖] [楼主帖] 楼主

北京联动北方科技有限公司
mysql是如何重用线程的呢?首先需要说明一下几个与此密切相关的全局变量的含义:
  • thread_count:当前线程数目,初始为0,由LOCK_thread_count保护
  • wake_thread:初始为0
  • cached_thread_count:初始为0,记录此时有多少线程被cached了

一个客户端连接请求和关闭的过程中,与创建、关闭线程密切相关的流程如下:

在附件中。

那么这里有几种情况:

1.不断处理客户端请求,没有客户端断开:
这种情况就不需要重用线程,因为没有客户端断开,因此没有线程被cached.因此每次响应客户端也就必须要创建新的线程.
这种情况总是有个度的,与我们设置的max_connection相关.

2.客户端请求与断开交替进行:
我们根据上图来分析,假设此时有n个线程在响应各自客户端的请求,假设接着4号线程的网络连接断开了,那么首先它要锁住thread_count,并且将其值减一,但此时并不立即释放thread_count的互斥锁:

pthread_mutex_lock(&LOCK_thread_count);
thread_count--;

接着调用cache_thread()来cache本线程,注意,这个时候如果有客户连接请求,是无法获得线程的(无论创建新的还是重用旧的),原因见上图”处理新客户连接请求”的开头,需要获得thread_count的互斥锁,但此锁刚刚已经被上锁了还未释放.

在cache_thread()函数中,关键部分:

1.cached_thread_count++;
2.while(...&&!wake_thread&&...)
3. pthread_cond_wait(&COND_thread_cache,&LOCK_thread_count);
4.cached_thread_count--;
5.if(wake_thread)
6.{
      7. wake_thread--;
      8. 新建一个THD,并将其与刚刚唤醒的thread绑定
9.}

先是将cached_thread_count自增1,代表多了一个cached的线程,接着while(…),由于wake_thread初值为0,因此调用第3行,这是linux下条件变量相关的一个api.
这个函数将执行:
1.释放LOCK_thread_count互斥锁(还记得不,刚刚这个互斥锁锁住之后还没释放呢),接着阻塞本线程,等待COND_thread_cache条件的发生.

2.好了,现在4号线程释放了LOCK_thread_count,并且阻塞了自己,等待COND_thread_count条件的发生.那么这个时候接下去会发生两种可能:
假设1:这时如果线程1也要关闭网络连接了,那么由于第1步中的pthread_cond_wait(…,&LOCK_thread_count)的调用,thread_count的互斥锁已经释放了,所以线程1也可以安全得进行到这一步,也是调用阻塞等待COND_thread_cache条件的发生,这时候cached_thread_count的值是2了.这种情况可以一直下去,cached_thread_count的值会不断增加,代表着缓存住的thread的不断增多,每缓存完一个线程,thread_count的互斥锁LOCK_thread_count都会被释放,但是在缓存一个thread的时候,这个互斥锁一直被锁着,也就是说不可能有多个线程在同时缓存自己,必须one by one.

假设2.如果这时候新来一个客户端请求,那么首先,获得LOCK_thread_count锁:

pthread_mutex_lock(&LOCK_thread_count);
thread_count++;

接着检查cached_thread_count > wake_thread是否满足,由于目前为止wake_thread一直为0,而4号线程在进入阻塞之前已经将cached_thread_count自增了,因此满足条件,执行if为真时的语句:

if( cached_thread_count > wake_thread)
{
       wake_thread++;
       pthread_cond_signal(*COND_thread_cache);
}
else
{
创建新线程
}
pthread_mutex_unlock(&LOCK_thread_count);

这个操作先是将wake_thread自增(此时变为1),再发送COND_thread_cache信号,最后释放LOCK_thread_count锁.
嘿,还记得不,刚才4号线程正在等待这个COND_thread_cache条件的发生了,于是4号线程醒了过来,这时4号线程再次锁住LOCK_thread_count锁(这是由pthread_cond_wait()函数所规定的),接着while()检查!wake_thread已经不满足条件了(这里我有个疑惑,为什么要用while()呢,直接用一个if不就可以了吗?),跳出循环,cached_thread_count减一,代表着减少了一个cache thread了,接着进入if语句,先是将wake_thread减1(又变成0了),再新建一个THD,并将其与刚刚唤醒的thread绑定,这里的内容就不展开了.最后释放LOCK_thread_count锁.

重用了的线程其内部的参数信息被更新为当前连接的客户端的信息,而线程本身却还是没有改变.
最后通过一步步地返回,回到了handle_one_connection中的那个for(;;)循环中,再次do_command();继续一步步地轮回.

我的理解大致就是这样一个过程.thread_count的互斥锁LOCK_thread_count在这个过程中扮演了重要的角色.
cached_thread_count和wake_thread也是,前者代表着”缓存池中有多少个thread”.后者在我目前的理解来说,更像是一个flag,对这个wake_thread,我还不是理解的很透彻.

原文发表在这里,非常欢迎讨论与拍砖~




赞(0)    操作        顶端 
总帖数
1
每页帖数
101/1页1
返回列表
发新帖子
请输入验证码: 点击刷新验证码
您需要登录后才可以回帖 登录 | 注册
技术讨论