从5.5.16开始,在MySQL的商业化版本中将Thread Pool作为plugin提供官方功能支持。在之前的版本中,线程处理模式包括两种:no-threads(单线程处理,多用于debug)、one-thread-per-connection(每个请求对应一个线程,目前被作为默认值);在支持thread pool功能的版本中,thread_handling则需设置为dynamically-loaded。
最初当我看到说MySQL会支持Thread Pool这个功能的时候,我很疑惑,心想不是已经有thread_cache_size来提高线程的重复利用率,为嘛还要弄个专门的池子呢。之前,有听过connection pool,是在一些应用服务器端来支持类似的功能。我们都知道,当应用发起一个对数据库的操作时,在整个应用中是一个不小的开销,从建立连接之初,CPU要给它划分一定的thread stack,然后进行用户身份认证,建立上下文信息,最后请求完成,关闭连接,同时释放资源,可以称的上是秒级的过程,在高并发的情况下,将给系统带来巨大的压力更不能保证性能。所以,采用线程重用,减小这部分的消耗。MySQL通过thread_cache_size这参数,来设置可以重用线程的个数,在生产过程中,通过一些状态参数来把握合适的重用线程数,比如:threads_cached可以知道目前有还有多少线程可用,通过threads_created参数的增长趋势可以判断是否需要加大需要cache住线程的个数。需要清楚的是目前,线程处理的模式是,每个请求就对应一个线程的模式,这就意味着当有成千上万的请求时,对应的也就需要成千上万的线程来相应这些请求,那么此刻问题就很明显了,系统的资源是有限的,必须要保证thread_number*thread_stack不能超过可以使用的内存资源,还要考虑CPU的调度能力,I/O的处理能力,这是一种很粗放的资源使用方式,不是吗?同时,这种不加控制的处理方式,也会带来资源使用的冲突,大量互斥锁的出现,性能的急剧下降。通过Thread Pool来控制确保不会超过服务器的最大负载能力,避免出现服务无响应,导致宕机的惨状。(既然在应用服务器端有connection pool,为什么还需要在数据库服务器端实现thread pool呢?)
在看了一些相关的资料和对于Thread Pool实现方式讨论之后,我目前最深刻的体会就是,控制,一个平衡的控制。没错,你可以说thread pool是为了提升性能,难道不是吗?我们所做的一切都是为了性能。但,如何让性能维持在一个稳定的状态,这才是当我们得到一个好的预期之后,我们更需要关心的重点。更多时候,系统的性能会随着并发的升高而随着或急或慢的下降,其实,我们更需要采用一种方式去做的时刻动态调整来为维持系统的稳定性能,减少波动,这对于我们的应用来说才会获得一个理想的性能。
我觉得,这更像是在跑马拉松,在整个过程中,不会因为你某一端跑的比别人快,最后一定就会第一个通过终点,而是取决于你以一个合理的速度在不断超越每一个身边的人,当你发现落后太多时适当提高速度,当体力透支时适当减慢速度,合理分担体能,保持稳定高效的前进。
关于Thread Pool的功能细节,大家可以去看手册5.5中相关章节的内容在7.11.6 The Thread Pool Plugin。本来想写一下,因为自己并没有亲自用过,就是放个中文在这里也没有多大用,想想还是算了,浪费大家时间(p.s.: Blog不应该是单纯的翻译,而且更不应该翻译的内容可能自己都没有用过的,只是可怜的how to install & configure :P)。
至于自己的体会上面说出来,还有没有说出来的都来自于Mikael Ronström的Blog,他是Thread Pool的开发人员,为了方便大家他近期又将之前一周的7/8篇文章整理到了一起供大家阅读和讨论,Here。
转载请注明:爱开源 » MySQL为什么要引入Thread Pool的线程处理模式