一夜之间发生MySql错误 - "发送到服务器的最后一个数据包是0毫秒前"

jkl*_*klp 8 java mysql tomcat

我似乎在一夜之间在我的应用程序中遇到异常.

我的环境是一个使用Tomcat的Java Web应用程序,用Java6编写并在MySQL上运行,Hibernate3用于连接数据库(使用MySQL连接器5.0.3 - mysql-connector-java-5.0.3-bin.jar)

有一个计划的作业在一夜之间运行(使用quartz作为调度程序),当在凌晨3点运行时,它在尝试访问数据库时给出以下异常(注意,我已经用"xxx"重命名了堆栈跟踪的位,因为它是我工作的公司的内部代码):

03:00:00 ERROR bernate.transaction.JDBCTransaction: JDBC begin failed
com.mysql.jdbc.CommunicationsException: Communications link failure due to underlying exception: 

** BEGIN NESTED EXCEPTION ** 

java.io.EOFException

STACKTRACE:

java.io.EOFException
    at com.mysql.jdbc.MysqlIO.readFully(MysqlIO.java:1913)
    at com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:2304)
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:2803)
    at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1573)
    at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:1665)
    at com.mysql.jdbc.Connection.execSQL(Connection.java:3118)
    at com.mysql.jdbc.Connection.setAutoCommit(Connection.java:5215)
    at org.apache.commons.dbcp.DelegatingConnection.setAutoCommit(DelegatingConnection.java:331)
    at org.apache.commons.dbcp.PoolingDataSource$PoolGuardConnectionWrapper.setAutoCommit(PoolingDataSource.java:317)
    at org.hibernate.transaction.JDBCTransaction.begin(JDBCTransaction.java:63)
    at org.hibernate.impl.SessionImpl.beginTransaction(SessionImpl.java:1326)
    at xxx.HibernateSession.beginThreadTransaction(HibernateSession.java:75)
    at xxx.HibernateSession.beginTransaction(HibernateSession.java:141)
    at xxx.TestCaseManager.runAllTestsInBackground(TestCaseManager.java:228)
    at xxx.scheduler.Job.execute(Job.java:42)
    at org.quartz.core.JobRunShell.run(JobRunShell.java:202)
    at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:529)


** END NESTED EXCEPTION **



Last packet sent to the server was 0 ms ago.
    at com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:2515)
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:2803)
    at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1573)
    at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:1665)
    at com.mysql.jdbc.Connection.execSQL(Connection.java:3118)
    at com.mysql.jdbc.Connection.setAutoCommit(Connection.java:5215)
    at org.apache.commons.dbcp.DelegatingConnection.setAutoCommit(DelegatingConnection.java:331)
    at org.apache.commons.dbcp.PoolingDataSource$PoolGuardConnectionWrapper.setAutoCommit(PoolingDataSource.java:317)
    at org.hibernate.transaction.JDBCTransaction.begin(JDBCTransaction.java:63)
    at org.hibernate.impl.SessionImpl.beginTransaction(SessionImpl.java:1326)
    at xxx.HibernateSession.beginThreadTransaction(HibernateSession.java:75)
    at xxx.HibernateSession.beginTransaction(HibernateSession.java:141)
    at xxx.TestCaseManager.runAllTestsInBackground(TestCaseManager.java:228)
    at xxx.scheduler.Job.execute(Job.java:42)
    at org.quartz.core.JobRunShell.run(JobRunShell.java:202)
    at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:529)
03:00:00 ERROR bernate.transaction.JDBCTransaction: JDBC begin failed
com.mysql.jdbc.CommunicationsException: Communications link failure due to underlying exception: 
Run Code Online (Sandbox Code Playgroud)

在早上,当登录到应用程序(也需要数据库访问)时,它会给出类似的异常,但在等待大约5分钟后再次尝试我们可以进入应用程序.

我检查了数据库,我可以对它试图连接的表执行简单的SELECT.任何帮助,将不胜感激.

Rom*_*eau 5

您的DBCP连接池超时使用以下配置...

简单的解决方案是在将DBCP提供给调用者之前进行验证.将以下属性添加到BasicDataSource配置:

<property name="testOnBorrow" value="true"/>
<property name="validationQuery" value="SELECT 1"/>
Run Code Online (Sandbox Code Playgroud)

有关所有选项的列表,请参见此处:http://commons.apache.org/dbcp/configuration.html

编辑:稍微纠正发生的事情,请参阅下面的MJB评论.

  • 要稍微纠正Romain,不是DBCP超时.这是MySQL服务器超时池中的各个连接 - mysql在8小时不活动后执行此操作.但是Romains的核心建议是正确的 (2认同)