首页 > 代码库 > 关于Mysql thread_concurrency和innodb_thread_concurren

关于Mysql thread_concurrency和innodb_thread_concurren

    原文地址:关于Mysql thread_concurrency和innodb_thread_concurrency参数的一点整理

    首先,最重要的一点,这个参数已经在最新版本的mysql中被移除了,官方最新5.7版本的doc上面对thread_concurrency有这样的说明:技术分享

    thread_concurrency变量是针对于Solaris 8及低版本的系统,设置了这个变量mysqld会调用thr_setconcurrency()函数。这个函数允许应用程序给同一时间运行的线程系统提示所需数量的线程。当前的Solaris 版本中这个参数已经没有作用了。这个参数在mysql 5.6.1中已经被标记为过时,在5.7.2版本的mysql中被移除。      

    对于thread_concurrency参数,这里有两篇文章可以参考:   

     thread_concurrency doesn’t do what you expect   

     mysql中优化thread_concurrency的误区     

     在 Mysql中事务隔离级别与binlog_format的一点理解中,我们简单的介绍过mysql的两种存储引擎:MyISAM和InnoDB,InnoDB支持事务,也是日常开发中常用的存储引擎,在InnoDB中,我们可以通过设置参数innodb_thread_concurrency限制线程的数量。       

    先来看一下官方doc 14.13.5 Configuring Thread Concurrency for InnoDBinnodb_thread_concurrency参数的配置说明,翻译如下:      

    InnoDB使用操作系统线程来处理用户的事务请求。(在事务提交或回滚之前可能给InnoDB引擎带来很多的请求)。在现代化操作系统和多核处理器的服务器,上下文切换是有效的,大多数工作负载运行没有任何并发线程数量的限制。在MySQL 5.5及以上版本中,MySQL做了可伸缩性的改进,它减少了这种在InnoDB内部限制并发执行线程数量的需要。      

    它有助于在最小化的情况下进行线程之间的上下文切换,InnoDB可以使用各种技术来限制操作系统并发执行线程的数量(因此大批量的请求可以在任何一个时间得到处理)。当InnoDB从用户会话收到一个新的请求,如果线程并发执行的数量达到预定义的限制,那么新的请求会先睡眠一段时间后再次尝试。在睡眠后不能按计划执行的请求会被放入先入/先出队列,并最终处理。那些等待获取锁的线程则不会被计入到并发执行线程的数量中。       我们可以通过设置配置参数innodb_thread_concurrency来限制并发线程的数量,一旦执行线程的数量达到这个限制,额外的线程在被放置到对队列中之前,会睡眠数微秒,可以通过设定参数innodb_thread_sleep_delay来配置睡眠时间。       

    在5.6.3之前的版本中,Mysql要求通过测试和实验找到innodb_thread_sleep_delay的最优值,这个最优值可能会因工作负载情况不同而发生改变。在MySQL 5.6.3及更高版本中,你可以通过设置参数innodb_adaptive_max_sleep_delay为innodb_thread_sleep_delay设置最大允许的值,InnoDB会根据当前线程调度活动自动调整innodb_thread_sleep_delay的值,这种动态调整机制有助于工作的线程,在系统负载低时或系统接近满负荷运转时,都能够顺利的调度      

    在MySQL 和 InnoDB之前的版本系列中,innodb_thread_concurrency的默认值,以及其隐含的限制并发线程执行的数量都进行过调整。在当前最新版本的mysql中,innodb_thread_concurrency的默认值为0,它表示默认情况下不限制线程并发执行的数量。      

    需要注意的是,InnoDB导致线程睡眠当且仅当并发线程的数量是有限的时候。如果对线程并发执行的数量没有限制,所有的请求都会被认为是可调度的,也就是说,如果innodb_thread_concurrency的值设置为0,innodb_thread_sleep_delay的值将会被忽略。      

    当有对线程数量进行限制(即innodb_thread_concurrency参数> 0),InnoDB通过允许多个请求在一个SQL语句执行过程中进入InnoDB,而不必遵守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。      

    对于innodb_thread_concurrency参数的作用及配置,这里有两篇文章可以参考:

       innodb_thread_concurrency的作用与改良  

      innoDb 的多线程并发调优      

    在官方doc上,对于innodb_thread_concurrency的使用,也给出了一些建议,如下:

  • 如果一个工作负载中,并发用户线程的数量小于64,建议设置innodb_thread_concurrency=0;

  • 如果工作负载一直较为严重甚至偶尔达到顶峰,建议先设置innodb_thread_concurrency=128,并通过不断的降低这个参数,96, 80, 64等等,直到发现能够提供最佳性能的线程数,例如,假设系统通常40到50个用户定期的数量增加6070甚至200。你会发现,性能80个并发用户设置时表现稳定,如果高于这个数,性能反而下降在这种情况下,建议设置innodb_thread_concurrency参数为80,以避免影响性能。

  • 如果你不希望InnoDB使用的虚拟CPU数量比用户线程使用的虚拟CPU更多(比如20个虚拟CPU),建议通过设置innodb_thread_concurrency 参数为这个值(也可能更低,这取决于性能体现),如果你的目标是将MySQL与其他应用隔离,你可以考虑绑定mysqld进程到专有的虚拟CPU。但是需 要注意的是,这种绑定,在myslqd进程一直不是很忙的情况下,可能会导致非最优的硬件使用率。在这种情况下,你可能会设置mysqld进程绑定的虚拟 CPU,允许其他应用程序使用虚拟CPU的一部分或全部。

  • 在某些情况下,最佳的innodb_thread_concurrency参数设置可以比虚拟CPU数量

  • 定期检测和分析系统,负载量、用户数或者工作环境的改变可能都需要对innodb_thread_concurrency参数的设置进行调整。

关于Mysql thread_concurrency和innodb_thread_concurren