跑项目时,发现log日志报如下异常:
com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Data source rejected establishment of connection, message from server: "Too many connections"数据库连接不够用。
我用的是SSH框架下的hibernateTemplate来操作数据库的,数据库连接池用的是c3p0(默认的最大连接数是100),mysql数据库提供的最大连接数是150:可以通过 show variables like '%max_connections%';查看数据库可提供的最大连接数,而show status like 'Threads%'可以通过Threads_connections监控当前数据库打开的连接数.
当时分析后,认为有2中可能的原因:
(1)hibernateTemple没有及时释放数据库连接。
(2)数据库的连接数确实不够用。
对于原因(1):
后来查了下 hibernate 的数据库连接释放策略,有如下4中策略:
default :默认方式,在spring中配置事务管理,由于事务颗粒度比较小,事务执行结束,也不会触发释放的操作,直至达到连接设置回收的最大超时时间才能回收连接,连接
会迟迟不释放,导致连接池被占满。
on_close :session关闭时,连接释放。
after_transaction :事务提交后,连接释放。
after_statement :每次执行statement 后就释放当前连接。
解决方案:由于hibernateTemplate每次执行完之后会自动关闭session,看如下源码:
protected Object doExecute(HibernateCallback action, boolean enforceNewSession, boolean enforceNativeSession)
throws DataAccessException { ......
finally {
if (existingTransaction) {
logger.debug("Not closing pre-bound Hibernate Session after HibernateTemplate");
disableFilters(session);
if (previousFlushMode != null) {
session.setFlushMode(previousFlushMode);
}
}
else {
// Never use deferred close for an explicitly new Session.
if (isAlwaysUseNewSession()) {
SessionFactoryUtils.closeSession(session);
}
else {
SessionFactoryUtils.closeSessionOrRegisterDeferredClose(session, getSessionFactory());
}
}
}
}
SessionFactoryUtils.closeSessionOrRegisterDeferredClose(session, getSessionFactory());
就是这段代码会自动关闭sessin。
所以我是用了on_close的策略去释放数据库连接,具体配置如下:(ps:如果你已经把transaction注入了dao包,采用after_transaction策略更好)
<prop key="hibernate.connection.release_mode">on_close</prop>
一般问题到此就会完美解决,但是楼主我比较悲催。
配完上面的策略后,楼主我的项目确实成功跑起来了。但是,跑了一会后又发现:
com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Data source rejected establishment of connection, message from server: "Too many connections"
。。。。。。
当时心中一万只什么的路过。难道是原因(2)? 我又对数据库 set global max_connections = 10000; (这条语句可以扩大数据库提供的连接数)并把连接池的最大连接数也设置到10000。项目再跑,发现上面的异常确实没了,但我的eclipse卡死了。。。又通过show status like 'Threads%'发现打开了1000多个连接。。。
这不应该啊,我只是同时并发了20条请求而已,算满也只需要60个连接啊。
后来,我只能认定c3p0数据库连接池的问题了。机缘巧合之下我发现了这个超高性能的数据库连接池:boneCP! 我的配置如下:
用了bongcp后,终于完美解决了com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Data source rejected establishment of connection, message from server: "Too many connections"的问题。<prop key="hibernate.connection.release_mode">on_close</prop>这个配置也起作用了!最重要的是bonecp的这条配置
<property name="releaseHelperThreads" value="3" />它自带连接释放机制。相当于多加了一条释放连接的保险!
最终要的是bonecp的性能比c3p0高了一倍左右(我项目的实测)。到此楼主的问题完美解决。
bonecp的详细介绍请参考:
http://zhoufoxcn.blog.51cto.com/792419/438277/
如果还不行的话,请参考我的
SSH下的Spring配置文件 这篇博客配置你的sping文件