在Mysql的默认设置中,如果一个数据库连接超过8小时没有使用(闲置8小时,即28800s),mysql server将主动断开这条连接。
在运维监控系统中,程序会报如下异常:
org.springframework.orm.hibernate3.HibernateJdbcException: JDBC exception on Hibernate data access; nested exception is org.hibernate.exception.GenericJDBCException: could not inspect JDBC autocommit mode
底层错误日志:
[130925-102435-381][ERROR][ActionQueue:afterTransactionCompletion 179]could not release a cache lock
org.hibernate.cache.CacheException: java.lang.IllegalStateException: The org.hibernate.cache.UpdateTimestampsCache Cache is not alive.
at org.hibernate.cache.EhCache.put(EhCache.java:125)
at org.hibernate.cache.UpdateTimestampsCache.invalidate(UpdateTimestampsCache.java:69)
at org.hibernate.engine.ActionQueue.afterTransactionCompletion(ActionQueue.java:174)
at org.hibernate.impl.SessionImpl.afterTransactionCompletion(SessionImpl.java:424)
at org.hibernate.jdbc.JDBCContext.afterTransactionCompletion(JDBCContext.java:225)
at org.hibernate.transaction.JDBCTransaction.rollback(JDBCTransaction.java:174)
at org.springframework.orm.hibernate3.HibernateTransactionManager.doRollback(HibernateTransactionManager.java:577)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processRollback(AbstractPlatformTransactionManager.java:631)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.rollback(AbstractPlatformTransactionManager.java:608)
at org.springframework.transaction.interceptor.TransactionAspectSupport.completeTransactionAfterThrowing(TransactionAspectSupport.java:328)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:111)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:652)
at com.sinosoft.sepmis.inspection.service.InspectionDataServiceImpl$$EnhancerByCGLIB$$d9f54f39.saveInspectionData()
at com.sinosoft.sepmis.util.ConnectionTelnet.execute(ConnectionTelnet.java:319)
at com.sinosoft.sepmis.util.InspectionUtil.inspectExecute(InspectionUtil.java:331)
at com.sinosoft.sepmis.util.InspectionUtil.partOfManual(InspectionUtil.java:259)
at com.sinosoft.sepmis.util.ThreadManageUtil.startInspect(ThreadManageUtil.java:45)
at com.sinosoft.sepmis.util.ThreadManageUtil.run(ThreadManageUtil.java:31)
at java.lang.Thread.run(Thread.java:735)
Caused by:
java.lang.IllegalStateException: The org.hibernate.cache.UpdateTimestampsCache Cache is not alive.
at net.sf.ehcache.Cache.checkStatus(Cache.java:1204)
at net.sf.ehcache.Cache.put(Cache.java:549)
at net.sf.ehcache.Cache.put(Cache.java:522)
at org.hibernate.cache.EhCache.put(EhCache.java:119)
... 19 more
原因分析:
由于程序后台一直在运行定时程序,而且定时程序的运行为7*24小时。在这期间程序会出现八小时闲置的情况,即程序和数据库之间没有任何交换操作。这样Mysql数据库端会主动动断开连接。这样如果定时启动后,要想获取到Mysql的连接,自然就会报出异常。
方法一,Mysql数据库延长wait_timeout参数时间(不推荐):
通过修改my.ini(Linux系统为my.cnf)文件中wait_timeout=xxx,即便是这样系统在闲着超过此参数设置时间后依然会出现异常。(注意:此参数单位为秒)
也可以通过mysql命令设置。
Mysql > set global wait_timeout=xxx;
设置后重启mysql服务,命令如下:
service mysql restart
登录mysql查看是否生效:
Mysql > show global variables like 'wait_timeout';
方法二,修改hibernate 中配置属性(不推荐):
代码如下
true property>
true property >
true property>
个人通过试验发现,这种方法并没有起到效果。不知道网上的写文章的人是怎么解决的。
方法三,使用第三方数据库连接池(推荐):
现在第三方数据库连接池使用较多的为c3p0,proxool等,在性能上c3p0稍好一些,原因c3p0数据库连接池,底层有一个定时查看数据库连接是否有效的参数。而且Hibernate的api中也推荐使用第三方数据库连接池,因为Hibernate本身的数据库连接池过于简单、本身存在bug。c3p0参数配置如下:
查看mysql数据库连接池情况,命令如下:
Mysql> show processlist;
ps:最近在在停起程序的时候我发现了一个问题,就算是我停止了服务,但是程序和mysql数据库之间的连接数依然没有断开,后来经查资料和同事请教,我发现在上边的c3p0配置存在一个小bug。因为我将c3p0交给Spring进行管理,但是在上边注入的bean中没有加上destroy-method="close"这个属性。 也就是说Spring是不能正常销毁连接的,由此出现了我说的问题。
写在这里以供大家警示,真是马虎啊,竟然忘记了销毁,实在不应该。
... ...
参考文章: