why

在5.6以前,mysql会对每个连接创建一个线程,请求结束后销毁线程。在高并发的情况下,为了避免频繁创建和释放线程,可以通过thread-cache将线程缓存起来,请求来了先尝试从cache中获取,重复利用线程资源。

show global status like 'thread%'

 show variables like 'thread_cache_size';

问题

在低并发的情况下,thread_cache可以成为一个有效的优化机制,但在并发突然增加时,会产生非常严重的问题。比如thead_cache_size是512,突然来了3000个连接怎么办?
mysql在5.6之前,会硬着头皮创建3000个线程!如果是一台一般配置的机器,比如32核、128G这种看起来还不错的配置,会因为线程上下文切换,导致整个实例无法及时响应问题,即使按主键查询,也可能超过1s,因此dba可能建议你:控制连接数在300左右。
通过客户端使用连接池技术,是可以控制总的连接个数,超过连接池最大值,客户端直接拒绝响应。但随着机器的扩大,在微服务还未完全的系统中,多个应用连一个库并非不可能,再诸如一个mysql实例多库的情况,更上雪上加霜。
通过在5.5版本上的遭遇,在3.5k的connections和threads情况下,mysql所在机器的cpu、memory不是性能陡然下降的原因,此时cpu有可能利用率很低,因为时间都花在了切换线程上下文上了,操作系统的资源也包括线程资源。
当然可以设置 max_connections,在连接过多时,拒绝信的连接请求

解决

https://dev.mysql.com/doc/refman/5.6/en/faqs-thread-pool.html
mysql 5.6引入了线程池技术,防止瞬间暴涨的连接击垮服务。

  • 一个线程可以处理多个连接
  • 连接被thread group管理起来,group的数量和cpu核心数相当,每个group最少有一个连接,达到最大程度利用cpu的效果,按连接的性质进行重要性排序和queued

适用场景

  • Threads_running变量持续较高,如innodb引擎中,总是超过40
  • 如果你在使用innodb_thread_concurrency来限制同时执行语句的数量,他们解决了相同的问题
  • 主要是短查询时
  • 较多的事务导致的资源竞争,导致获取锁的时间消耗变大,thread pool将减少这样的竞争

经验值

https://dev.mysql.com/doc/refman/5.6/en/thread-pool-tuning.html

thread_pool_size :线程组数量,默认16,建议16-36,最好是24-36,值的范围1-64,否则报错(线程组数量与cpu相当,每个线程组中有WorkerThread,ListenThread)

thread_pool_stall_limit:将一个sql打标成stall的时间的阈值,意思为这个sql占用了较长的时间,资源该让给其它请求了,较低的值允许线程更快的启动起来;避免死锁。较高的值适合于长时间运行的语句,避免当前语句执行时有太多其他语句执行

http://database.51cto.com/art/201803/569007.htm

每一个group有多个worker线程,一个worker线程可以处理多个连接的sql,可以按优先级进行队列排序,比如默认的按事务排序

show global variables like ‘%thread_handling%‘;

posted on 2018-10-26 14:52  j.liu windliu  阅读(1170)  评论(2编辑  收藏  举报