本节提供有关设置线程池系统变量以获得最佳性能的准则,该准则使用诸如每秒事务之类的度量标准进行度量。
thread_pool_size是控制线程池性能的最重要参数。只能在服务器启动时设置。我们在测试线程池方面的经验表明:
-
如果主存储引擎是
InnoDB,则最佳thread_pool_size设置可能在16到36之间,最常见的最佳值往往在24到36之间。我们没有看到任何设置超过36的最佳情况。在小于16的最佳值的特殊情况下。对于DBT2和Sysbench之类的工作负载,最佳选择
InnoDB通常通常约为36。对于非常密集的写工作负载,最佳设置有时可能会更低。 -
如果主存储引擎是
MyISAM,则该thread_pool_size设置应该相当低。最佳性能通常是4到8之间的值。较高的值往往会对性能产生轻微的负面影响,但影响不大。
另一个系统变量 thread_pool_stall_limit对处理阻塞的和长时间运行的语句很重要。如果所有阻止MySQL服务器的调用都报告给线程池,它将始终知道何时阻止执行线程。但是,这可能并不总是正确的。例如,在未使用线程池回调进行检测的代码中可能发生块。对于这种情况,线程池必须能够识别似乎被阻塞的线程。这可以通过超时来完成,可以使用thread_pool_stall_limit 系统变量来调整其长度。此参数确保服务器不会被完全阻止。的价值 thread_pool_stall_limit 上限为6秒,以防止服务器死锁的风险。
thread_pool_stall_limit还使线程池能够处理长时间运行的语句。如果允许长时间运行的语句阻止线程组,则分配给该组的所有其他连接都将被阻止,并且直到长时间运行的语句完成后才能开始执行。在最坏的情况下,这可能需要数小时甚至数天。
thread_pool_stall_limit应该选择 的值, 以使执行时间长于其值的语句被视为已停止。停顿的语句会产生很多额外的开销,因为它们涉及额外的上下文切换,并且在某些情况下甚至会涉及额外的线程创建。另一方面,将thread_pool_stall_limit 参数设置 得太高意味着长时间运行的语句将阻塞许多短时间运行的语句,其持续时间超过了必要。较短的等待值使线程可以更快地启动。较短的值也可以更好地避免死锁情况。长等待值对于包含长时间运行的语句的工作负载很有用,以避免在当前语句执行时启动太多新语句。
假设服务器执行一个工作负载,即使加载了服务器,其中99.9%的语句在100ms内完成,其余的语句花费100ms到2个小时相当均匀地散布。在这种情况下,将其设置 thread_pool_stall_limit为10(意味着100ms)是有意义的。默认值60ms适用于主要执行非常简单的语句的服务器。
thread_pool_stall_limit 可以在运行时更改 该参数,以使您达到适合服务器工作负载的平衡。假设tp_thread_group_stats已启用该 表,则可以使用以下查询来确定已暂停的已执行语句的比例:
SELECT SUM(STALLED_QUERIES_EXECUTED) / SUM(QUERIES_EXECUTED)
FROM performance_schema.tp_thread_group_stats;
此数字应尽可能低。要减少语句停顿的可能性,请增加的值 thread_pool_stall_limit。
一条语句到达时,在实际开始执行之前最多可以延迟多少时间?假设满足以下条件:
- 低优先级队列中有200条语句排队。
- 高优先级队列中有10条语句排队。
thread_pool_prio_kickup_timer设置为10000(10秒)。thread_pool_stall_limit设置为100(1秒)。
在最坏的情况下,这10个高优先级语句表示10个长时间连续执行的事务。因此,在最坏的情况下,不会将任何语句移到高优先级队列,因为它始终已经包含等待执行的语句。10秒钟后,新语句可以移动到高优先级队列中。但是,在可以移动它之前,必须先移动它之前的所有语句。这可能还要花费2秒的时间,因为每秒最多将100条语句移到高优先级队列。现在,当语句到达高优先级队列时,它前面可能会存在许多长时间运行的语句。在最坏的情况下 从高优先级队列中检索下一个语句之前,每个语句都会停滞,每个语句将花费1秒。因此,在这种情况下,将需要222秒才能开始执行新语句。
此示例显示了应用程序的最坏情况。如何处理取决于应用程序。如果应用程序对响应时间有很高的要求,则它很可能应该将用户本身限制在更高的级别。否则,它可以使用线程池配置参数来设置某种最大等待时间。




