配置InnoDB的并发线程
InnoDB使用操作系统线程来处理来自用户事务的请求。(事务可能会在提交或回滚之前向InnoDB发出很多请求。)在具有多核处理器的现代操作系统和服务器上,上下文切换非常高效,大多数工作负载不受并发线程数量的限制而运行良好。MySQL 5.5及以上版本的可伸缩性改进减少了InnoDB需要并发执行线程的数量。
在线程之间最小化上下文切换的情况下,InnoDB可以使用许多技术来限制并发执行的操作系统线程的数量(从而限制同一时间处理的请求的数量)。当InnoDB收到一个来自用户会话的新请求时,如果并发执行的线程数在预定义的限制下,新请求会休眠一段时间,然后重试。一个在休眠后不能重新调度的请求被放入优先/优先出队列并最终被处理。等待锁的线程不计入并发执行的线程数。
可以通过设置配置参数innodb_thread_concurrency来限制并发线程的数量。一旦执行线程的数量达到这个限制,在被放入队列之前,额外的线程将休眠数微秒,由配置参数Innodb_thread_sleep_delay设置。
以前,需要通过实验来找到innodb_thread_sleep_delay的最佳值,而最佳值可能会根据工作负载的不同而变化。在MySQL 5.6.3及以上版本中,你可以设置innodb_adaptive_max_sleep_delay配置选项为innodb_thread_sleep_delay设置最大值,InnoDB会根据当前的线程调度活动自动调整innodb_thread_sleep_delay的大小。这种动态调整有助于线程调度机制在系统负载较轻和正常运行时顺利工作。
innodb_thread_concurrency的默认值和默认的并发线程数限制在不同版本的MySQL和InnoDB中都有改变。innodb_thread_concurrency的默认值是0,因此默认情况下没有并发执行线程的数量限制。
InnoDB只在并发线程数量有限的情况下才会导致线程休眠。当对线程的数量没有限制时,所有线程都平等地进行调度。也就是说,如果innodb_thread_concurrency为0,则忽略innodb_thread_sleep_delay的值。
当线程数量有限制时(当innodb_thread_concurrency为> 0时),InnoDB通过在执行单个SQL语句时允许同时执行多个请求来减少上下文切换的开销,而不用遵守innodb_thread_concurrency设置的限制。由于一条SQL语句(比如join)可能包含在InnoDB内的多个行操作,InnoDB会分配指定数量的“票据”,允许以最小的开销重复调度一个线程。
当一个新的SQL语句启动时,线程没有票据,它必须观察innodb_thread_concurrency。一旦线程被授予进入InnoDB的权限,它就会被分配大量的票据,这些票据可以用来随后进入InnoDB执行行操作。如果票据用完,线程将被驱逐,并且再次观察到innodb_thread_concurrency,这可能会将该线程放入等待线程的先入先出队列中。当线程再次被授予进入InnoDB的权限时,会再次分配票据。分配的票据数量由全局选项innodb_concurrency_tickets指定,默认值为5000。当锁可用时,等待锁的线程将获得一张票据。
这些变量的正确值取决于您的环境和工作负载。尝试一系列不同的值,以确定哪些值适合您的应用程序。在限制并发执行线程的数量之前,检查一下可以提高多核和多处理器计算机上InnoDB性能的配置选项,比如innodb_adaptive_hash_index。