1 知道 sleep 线程过多原因
首先要知道到底是什么原因导致的 sleep 线程过多的:
-
程序逻辑问题,导致连接一直不释放;
-
mysql 参数的问题,是不是参数配置的不合理,一直不释放连接;
-
mysql 语句的问题,数据库查询不够优化,过度耗时。
-
大并发情况问题,导致 sleep 情况过多;
2 临时解决 sleep 线程
很多人都是重启大法,重启大法确实好, 能够释放,生产重启对业务有影响的,不能随便重启的
shell脚本+cron计划任务,来kill sleep 线程,这个不靠谱啊, 你不知道 sleep 线程,里面是不是还有事务还在执行没有提交,也是sleep 状态,这个kill 操作有点莽夫,对生产数据数据库还是要理智啊。
我临时解决的办法:
-
对用户资源做限制,看看那个用户连接的sleep线程比较多,对这个用户连接多的做一些限制,比如一个小时可以连接多少次啊等等
-
修改 mysql 参数问题 ,修改
wait_timeout
和interactive_timeout
默认都是28800秒有,也就是8个小时以后才释放空链接。
例子:
不同用户登录到数据库,wait_timeout和interactive_timeout
都是28800秒
修改参数,我生产环境设置的是半个小时,也就是1800秒
1 2 3 4 5 6 7 |
mysql> set global wait_timeout=1800;
mysql> set global interactive_timeout=1800;
shell> vim my.cnf
[mysqld]
wait_timeout=1800
interactive_timeout=1800
|
这样修改完,由于已近保持的会话连接需要等到8个小时才会释放, 所以修改了wait_timeout和interactive_timeout
不会立即生效的原因,这时候就要修改连接过多的用户资源了来释放sleep线程了
如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
#开启两个会话窗口
mysql> # 重新登录了会话,wait_timeout和interactive会生效
mysql> show variables like 'wait_timeout' ;
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| wait_timeout | 1800 |
+---------------+-------+
1 row in set (0.00 sec)
mysql> show variables like 'interactive_timeout' ;
+---------------------+-------+
| Variable_name | Value |
+---------------------+-------+
| interactive_timeout | 1800 |
+---------------------+-------+
1 row in set (0.00 sec)
#session2
mysql> #这个是其他用户连接的mysql,这个会话一直没有断开,参数还是28800
mysql> show variables like 'wait_timeout' ;
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| wait_timeout | 28800 |
+---------------+-------+
1 row in set (0.01 sec)
mysql> show variables like 'interactive_timeout' ;
+---------------------+-------+
| Variable_name | Value |
+---------------------+-------+
| interactive_timeout | 28800 |
+---------------------+-------+
1 row in set (0.00 sec)
|
3 怎么根本解决
这时候就要知道 造成 sleep 线程过多的原因来解决:
-
程序执行完毕,应该显式调用mysql_close
-
程序中根据业务访问情况,选择长连接还是短连接
-
能逐步分析系统的SQL查询,找到查询过慢的SQL优化
-
合理设置mysql参数值