线程池的线程组,每个管理一组客户端连接。在建立连接,线程池以循环的方式分配给线程组。
线程池暴露系统变量可以用来配置其操作:
thread_pool_algorithm
:并发算法用于调度。thread_pool_high_priority_connection
:如何安排语句执行一个会话。thread_pool_max_active_query_threads
:每组允许多少活动线程。thread_pool_max_unused_threads
:有多少线程允许睡觉。thread_pool_prio_kickup_timer
多久之前,线程池移动声明从低优先级队列中等待执行到高优先级队列。thread_pool_size
:线程池中的线程组的数量。这是最重要的参数控制线程池的性能。thread_pool_stall_limit
:一个执行语句之前被认为是停滞不前。
配置线程组的数量,使用thread_pool_size
系统变量。默认的组数是16。指南设置这个变量,看到部分5.6.3.4,“线程池调优”。
每组的最大线程数是4096(或4095在一些系统内部使用一个线程)。
线程池分离连接和线程,所以没有固定的连接关系和收到这些连接的线程执行语句。这不同于默认的线程处理模型,将一个线程与一个连接,这样一个给定线程执行所有语句的连接。
默认情况下,线程池试图确保每组最多一个线程执行,在任何时候,但有时暂时允许多个线程执行最佳性能:
每个线程组有一个侦听器线程侦听传入语句的连接分配给组。当声明到达时,线程组立即开始执行它或队列以后执行:
立即执行发生如果声明是唯一一个接收和不排队或当前执行语句。
排队时如果声明不能立即开始执行。
如果发生立即执行,侦听器线程执行它。(这意味着暂时没有线程组中的听。)如果语句完成很快,执行线程返回监听语句。否则,线程池认为声明开始停滞不前,另一个线程作为侦听器线程(如果必要创建它)。以确保没有线程组就被停滞的语句,线程池有一个后台线程,定期监控线程组。
通过使用监听线程执行一个语句,可以立即开始,不需要创建额外的线程,如果语句快速完成。这样可以确保最有效的执行可能的低并发线程的数量。
当线程池插件启动时,它会创建一个线程每组(侦听器线程),加上后台线程。根据需要创建额外的线程执行语句。
的值
thread_pool_stall_limit
系统变量决定的意义”很快就完成”在前面的项目。默认线程之前被认为是停滞不前是60 ms但最多可以设置为6。这个参数是可配置的,使您能够适合服务器工作负载平衡。短暂的等待值允许线程开始更快。短值也更好的避免死锁的情况。漫长的等待值是有用的工作负载,包括长期运行的语句,以避免启动太多新语句,而当前的执行。如果
thread_pool_max_active_query_threads
是0,默认的算法应用和确定每组活动线程的最大数量。默认的算法考虑了线程停滞,可能暂时允许更多的活动线程。如果thread_pool_max_active_query_threads
大于0,它限制每组活动线程的数量。线程池集中在限制并发短时间运行的语句的数量。执行语句之前到达拖延时间,它可以防止其他语句开始执行。如果语句执行过去的停滞时间,允许继续但不再阻止其他语句开始。这样,线程池试图确保每个线程组中没有超过一个短时间运行的语句,尽管可能有多个长期运行的语句。这是不可取的,让长时间运行的语句阻止其他语句执行,因为没有限制的等待可能是必要的。例如,复制源服务器,一个线程发送二进制日志事件永远副本有效运行。
声明变得阻塞如果遇到磁盘I / O操作或用户级锁(锁行锁或表)。块将导致线程组成为未使用,所以有回调线程池的线程池,以确保可以立即开始一个新的线程在这个组执行另一个语句。当一个阻塞的线程返回,线程池允许立即重启。
有两个队列,一个高优先级队列和一个低优先级队列。第一个语句在事务的优先级队列。任何以下语句的事务去高优先级队列,如果事务(它已经开始执行语句),或低优先级队列。队列的任务可以通过使受到影响
thread_pool_high_priority_connection
系统变量,导致所有排队语句会话进入高优先级队列。语句nontransactional存储引擎,或事务引擎
自动提交
启用,被视为低优先级的语句,因为在这种情况下每个语句是一个事务。因此,给定的语句InnoDB
和MyISAM
表、线程池的重视InnoDB
在这些MyISAM
除非自动提交
启用。与自动提交
启用,所有语句都低优先级。当线程组选择排队语句执行,它首先在高优先级队列,然后在低优先级队列。如果找到的一份声明中,它从队列中删除并开始执行。
如果声明保持在低优先级队列太长,线程池移动到高优先级队列。的值
thread_pool_prio_kickup_timer
系统变量控制时间运动。对于每个线程组,最多一个语句每10 ms每秒(100)从低优先级队列移动到高优先级队列。线程池重用最活跃线程获得更好的CPU缓存的使用。这是一个小的调整,对性能有很大的影响。
当一个线程执行一个语句从用户连接,仪表性能模式帐户用户线程活动连接。否则,性能模式帐户活动的线程池。
这里有条件的例子,一个线程组可能有多个线程开始执行语句:
一个线程开始执行一个语句,但运行时间长到足以被认为是停滞不前。线程组允许另一个线程开始执行另一个语句甚至通过第一个线程仍在执行。
一个线程开始执行一个语句,然后变得阻塞和报告返回线程池。线程组允许另一个线程开始执行另一个语句。
一个线程开始执行一个语句,变得阻塞,但没有报告,它阻止了,因为不会发生在代码块被装备与线程池回调。在这种情况下,线程似乎仍在运行的线程组。如果块声明被认为是持续足够长的时间停滞,该集团允许另一个线程开始执行另一个语句。
线程池设计为可伸缩在越来越多的连接。也是为了避免死锁,可以来自限制数量的积极执行语句。重要的是,不报告返回线程池的线程不阻止其他语句执行,从而导致线程池成为陷入僵局。这样的声明的例子:
长时间运行的语句。这些会导致只有少数语句使用的所有资源,他们可以阻止所有其他访问服务器。
二进制日志转储线程读二进制日志和寄副本。这是一种长期的”声明”运行很长一段时间,不应该阻止其他语句执行。
语句行锁阻塞,表锁,睡眠,或任何其他阻塞活动并没有报告给线程池MySQL服务器或存储引擎。
在每种情况下,为了防止死锁,该声明是搬到停滞类别不完整的很快,所以线程组可以允许另一个语句开始执行。通过这个设计,当一个线程执行或阻塞在较长时间,停滞不前的线程池线程移动的类别和语句的执行,它不会阻止其他语句执行。
可能发生的最大线程数的总和max_connections
和thread_pool_size
。这可能发生在一个情况下所有连接执行模式,创建了一个额外的线程每组听更多的语句。这未必是一个国家,经常发生,但它在理论上是可能的。