一:问题描述:
mysql性能突然降低,连接数突然增加,正常也就不到50个,如下;
root@localhost : (none) 18:34:48>select count(user) from information_schema.processlist group by user;
+-------------+
| count(user) |
+-------------+
| 230 |
| 150 |
| 3 |
| 8 |
| 6 |
| 2 |
| 1 |
| 17 |
+-------------+
8 rows in set (0.00 sec)
二:问题分析:
Innodb用自己的线程调度机制来控制线程如何进入innodb内核工作,并执行相关的操作。
当一个线程需要进入到Innodb存储引擎层(以下简称Innodb),Innodb会检查已经进入到Innodb存储引擎层的线程总数是否超过innodb_thread_concurrency;如果超过了,则该线程需要等待innodb_thread_sleep_delay毫秒再次进行尝试;如果尝试仍然失败,该线程将会进入到FIFO的队列中进行等待唤醒(此时状态为sleeping)。 一旦该thread进入到INNODB中,该线程将会获得innodb_concurrency_tickets次通行证,即该线程在接下来的innodb_concurrency_tickets次进入到INNODB中都不需要再进行检查,可直接进入。
线程尝试两次进入INNODB存储引擎层的目的是,减少等待线程的数量以及减少上下文切换。
Innodb并发参数:
1) innodb_thread_concurrency
同一时刻能够进入innodb层并发执行的线程数量。如果超过CPU核数,某些线程就会处于就绪状态;若Server层线程数超过这个数值,多余的线程会被放到wait queue队列中等待;
默认值:0,表示不限制线程并发执行的数量,所有请求都会被认为是可调度的。此时,innodb_thread_sleep_delay的值会被忽略
范围:0 ~ 1000
2) innodb_commit_concurrency
同一时刻允许同时commit的线程数量
默认值:0,即不限制
范围:0 ~ 1000
如果 innodb_thread_concurrency 设置的有点大innodb_commit_concurrency应该做出相应的调整,否则会造成大量线程阻塞。
3) innodb_concurrency_tickets
thread进入INNODB中,会获得innodb_concurrency_tickets次通行,该线程在接下来的innodb_concurrency_tickets次进入到INNODB中不需要再进行检查,可直接进入。
默认值:5000
范围:0 ~ 4294967295
4) innodb_thread_sleep_delay
线程未能进入INNODB存储引擎,需要等待innodb_thread_sleep_delay毫秒再次尝试进入;即进入wait queue前sleep的时间;
单位:微妙
默认值:10000
在官方doc上,对于innodb_thread_concurrency的使用,也给出了一些建议,如下:
1. 如果一个工作负载中,并发用户线程的数量小于64,建议设置innodb_thread_concurrency=0;
2.如果工作负载一直较为严重甚至偶尔达到顶峰,建议先设置inn