无情 @ Fri Oct 09 10:46:50 CST 2015 阅读(3519)
MyBatis 连接池


前几天一朋友联系我说他们新上的项目访问10分钟后就出现很慢的情况,让我帮他们看下。我拿到他们网站地址后开始查找问题,

我分别测试了网站的IP网络情况,发现没有问题。然后我就去查看系统日志,发现一直在报一个错误。



Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: No operations allowed after connection closed.
at sun.reflect.GeneratedConstructorAccessor560.newInstance(Unknown Source)
at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
at com.mysql.jdbc.Util.handleNewInstance(Util.java:411)
at com.mysql.jdbc.Util.getInstance(Util.java:386)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1013)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:987)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:982)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:927)
at com.mysql.jdbc.ConnectionImpl.throwConnectionClosedException(ConnectionImpl.java:1205)
at com.mysql.jdbc.ConnectionImpl.checkClosed(ConnectionImpl.java:1197)
at com.mysql.jdbc.ConnectionImpl.setAutoCommit(ConnectionImpl.java:4954)
at org.jboss.resource.adapter.jdbc.BaseWrapperManagedConnection.checkTransaction(BaseWrapperManagedConnection.java:547)
at org.jboss.resource.adapter.jdbc.WrappedConnection.checkTransaction(WrappedConnection.java:836)
at org.jboss.resource.adapter.jdbc.WrappedConnection.prepareStatement(WrappedConnection.java:250)
at sun.reflect.GeneratedMethodAccessor379.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.hibernate.engine.jdbc.internal.proxy.ConnectionProxyHandler.continueInvocation(ConnectionProxyHandler.java:138)
… 123 more
Caused by: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure


意思很明确:数据库连接超时不允许被执行。


我又查看了数据库连接是否配置不够或者连接数占用满了,结果答案都是否定的。



那么究竟那里出问题了  我开始问百度,给出的全部解决方案是:


Mysql服务器默认的“wait_timeout”是8小时,也就是说一个connection空闲超过8个小时,Mysql将自动断开该connection。这就是问题的所在,在C3P0 pools中的connections如果空闲超过8小时,Mysql将其断开,而C3P0并不知道该connection已经失效,如果这时有Client请求connection,C3P0将该失效的Connection提供给Client,将会造成上面的异常。


解决的方法有3种:


增加 wait_timeout 的时间。

减少 Connection pools 中 connection 的 lifetime。

测试 Connection pools 中 connection 的有效性。

当然最好的办法是同时综合使用上述3种方法,下面就 DBCP、C3P0 和 simple jdbc dataSource 分别做一说明,假设 wait_timeout 为默认的8小时


结果还是没有解决

那么到底为什么会导致超时,已经排除了数据库配置问题,这时我突然想到是否是sql语句的慢查询导致执行时间过长系统一直处于等待状态,于是在数据库执行了show full processlist  果然发现有一条超级复杂sql语句一直在执行 执行时间超过20秒

于是优化了这调sql语句日志就不再报错了问题彻底解决


其实原因很简单:sql语句执行时间一长,如果你在连接池设置的响应时间短了,数据库还在执行你的数据,你的连接池断开了,于是系统就报错了



总结:sql语句的优化对项目性能起到很大的作用。