在MySQL中运行SHOW PROCESSLIST;,现数据库中有很多这样的进程:
上图可以看出,bim用户发起了274个连接,都是sleep状态。MySQL中Sleep连接过多,那么造成sleep的原因,有三个,下面是mysql手册给出的解释:
1)客户端程序在退出之前没有调用mysql_close()。[写程序的疏忽,或者数据库的db类库没有自动关闭每次的连接]
2)客户端sleep的时间在wait_timeout或interactive_timeout规定的秒内没有发出任何请求到服务器。[类似常连,类似于不完整的tcp ip协议构造,服务端一直认为客户端仍然存在(有可能客户端已经断掉了)]
3)客户端程序在结束之前向服务器发送了请求还没得到返回结果就结束掉了。[参看:tcp ip协议的三次握手]
解决的方法也很简单
睡眠连接过多,会对mysql服务器造成什么影响?严重消耗mysql服务器资源(主要是cpu, 内存),并可能导致mysql崩溃。造成睡眠连接过多的原因?
1)使用了太多持久连接(个人觉得,在高并发系统中,不适合使用持久连接)。
2)程序中,没有及时关闭mysql连接。
3)数据库查询不够优化,过度耗时。
那么,如果要从根本上解决sleep连接过多,就得从以上三点反复检查,但是见效并不快。
那么更好的办法应该是让mysql自己决定这些睡眠连接的命运,实施会更简单,有效。
mysql的配置文件中,有一项:wait_timeout, 即可设置睡眠连接超时秒数,如果某个连接超时,会被mysql自然终止,多好的办法!
如设置:
1 2 |
[mysqld] wait_timeout=10 |
即设置mysql连接睡眠时间为60秒,任何sleep连接睡眠时间若超过60秒,将会被mysql服务自然终止,要比编写shell脚本更简单。那么,对于正在运行中的生产服务器,在不能停止服务情况下,修改此项怎么办?很简单,以root用户登录到mysql,执行:
1 |
mysql> set global wait_timeout=60; |
当然,更根本的方法,还是从以上三点排查之:
1. 程序中,不使用持久链接,即使用mysql_connect而不是mysql_pconnect。
2. 程序执行完毕,应该显式调用mysql_close。
3. 只能逐步分析系统的SQL查询,找到查询过慢的SQL,优化之。
最后说一下,我出现这个问题是因为java有一个连接池复用,类似长连接理解吧。