我有一个使用hibernate(v3.6.4)的应用程序,其中连接池由C3P0(v0.9.1.2)提供.
问题是如果我进行数据库查询,如果应用程序进程(以及C3P0池)运行的时间超过MySQL wait_timeout值,则会导致JDBC通信链接失败.为了测试这个问题,我将/etc/MysqL/my.cnf中的wait_timeout值设置为600秒:
2013-01-27 20:08:00,088 ERROR [Thread-0] (JDBCExceptionReporter.java:234) - Communications link failure
The last packet successfully received from the server was 665,943 milliseconds ago. The last packet sent successfully to the server was 6 milliseconds ago.
org.hibernate.exception.JDBCConnectionException: Could not execute query
at org.hibernate.exception.sqlStateConverter.convert(sqlStateConverter.java:99)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66)
at org.hibernate.loader.Loader.doList(Loader.java:2536)
at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2276)
at org.hibernate.loader.Loader.list(Loader.java:2271)
at org.hibernate.loader.criteria.CriteriaLoader.list(CriteriaLoader.java:119)
at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1716)
at org.hibernate.impl.Criteriaimpl.list(Criteriaimpl.java:347)
.....
Caused by: com.MysqL.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure
The last packet successfully received from the server was 665,943 milliseconds ago. The last packet sent successfully to the server was 6 milliseconds ago.
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(UnkNown Source)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(UnkNown Source)
at java.lang.reflect.Constructor.newInstance(UnkNown Source)
at com.MysqL.jdbc.Util.handleNewInstance(Util.java:411)
at com.MysqL.jdbc.sqlError.createCommunicationsException(sqlError.java:1116)
at com.MysqL.jdbc.MysqLIO.reuseAndReadPacket(MysqLIO.java:3102)
at com.MysqL.jdbc.MysqLIO.reuseAndReadPacket(MysqLIO.java:2991)
at com.MysqL.jdbc.MysqLIO.checkerrorPacket(MysqLIO.java:3532)
at com.MysqL.jdbc.MysqLIO.sendCommand(MysqLIO.java:2002)
at com.MysqL.jdbc.MysqLIO.sqlQueryDirect(MysqLIO.java:2163)
at com.MysqL.jdbc.ConnectionImpl.execsql(ConnectionImpl.java:2624)
at com.MysqL.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:2127)
at com.MysqL.jdbc.PreparedStatement.executeQuery(PreparedStatement.java:2293)
at com.mchange.v2.c3p0.impl.NewProxyPreparedStatement.executeQuery(NewProxyPreparedStatement.java:76)
at org.hibernate.jdbc.AbstractBatcher.getResultSet(AbstractBatcher.java:208)
at org.hibernate.loader.Loader.getResultSet(Loader.java:1953)
at org.hibernate.loader.Loader.doQuery(Loader.java:802)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:274)
at org.hibernate.loader.Loader.doList(Loader.java:2533)
... 9 more
Caused by: java.io.EOFException: Can not read response from server. Expected to read 4 bytes, read 0 bytes before connection was unexpectedly lost.
at com.MysqL.jdbc.MysqLIO.readFully(MysqLIO.java:2552)
at com.MysqL.jdbc.MysqLIO.reuseAndReadPacket(MysqLIO.java:3002)
... 22 more
2013-01-27 20:19:00,179 WARN [Thread-0] (NewPooledConnection.java:487) - [c3p0] Another error has occurred [ com.MysqL.jdbc.exceptions.jdbc4.CommunicationsException: The last packet successfully received from the server was 1,326,037 milliseconds ago. The last packet sent successfully to the server was 660,100 milliseconds ago. is longer than the server configured value of 'wait_timeout'. You should consider either expiring and/or testing connection validity before use in your application, increasing the server configured values for client timeouts, or using the Connector/J connection property 'autoReconnect=true' to avoid this problem. ] which will not be reported to listeners!
com.MysqL.jdbc.exceptions.jdbc4.CommunicationsException: The last packet successfully received from the server was 1,326,037 milliseconds ago. The last packet sent successfully to the server was 660,100 milliseconds ago. is longer than the server configured value of 'wait_timeout'. You should consider either expiring and/or testing connection validity before use in your application, increasing the server configured values for client timeouts, or using the Connector/J connection property 'autoReconnect=true' to avoid this problem.
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(UnkNown Source)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(UnkNown Source)
at java.lang.reflect.Constructor.newInstance(UnkNown Source)
at com.MysqL.jdbc.Util.handleNewInstance(Util.java:411)
at com.MysqL.jdbc.sqlError.createCommunicationsException(sqlError.java:1116)
at com.MysqL.jdbc.MysqLIO.send(MysqLIO.java:3364)
at com.MysqL.jdbc.MysqLIO.sendCommand(MysqLIO.java:1983)
at com.MysqL.jdbc.MysqLIO.sqlQueryDirect(MysqLIO.java:2163)
at com.MysqL.jdbc.ConnectionImpl.execsql(ConnectionImpl.java:2624)
at com.MysqL.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:2127)
at com.MysqL.jdbc.PreparedStatement.executeQuery(PreparedStatement.java:2293)
at com.mchange.v2.c3p0.impl.NewProxyPreparedStatement.executeQuery(NewProxyPreparedStatement.java:76)
at org.hibernate.jdbc.AbstractBatcher.getResultSet(AbstractBatcher.java:208)
at org.hibernate.loader.Loader.getResultSet(Loader.java:1953)
at org.hibernate.loader.Loader.doQuery(Loader.java:802)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:274)
at org.hibernate.loader.Loader.doList(Loader.java:2533)
at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2276)
at org.hibernate.loader.Loader.list(Loader.java:2271)
at org.hibernate.loader.criteria.CriteriaLoader.list(CriteriaLoader.java:119)
at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1716)
at org.hibernate.impl.Criteriaimpl.list(Criteriaimpl.java:347)
....
Caused by: java.net.socketException: broken pipe
at java.net.socketoutputStream.socketWrite0(Native Method)
at java.net.socketoutputStream.socketWrite(UnkNown Source)
at java.net.socketoutputStream.write(UnkNown Source)
at java.io.bufferedoutputstream.flushBuffer(UnkNown Source)
at java.io.bufferedoutputstream.flush(UnkNown Source)
at com.MysqL.jdbc.MysqLIO.send(MysqLIO.java:3345)
... 20 more
这看起来像是一个常见的问题,所以为了解决这个问题,我在检查了hibernate / c3p0文档并回答了有关Stack Overflow的已经问过的问题后,尝试调整这些hibernate / c3p0属性:
相关的hibernate属性:
<property name="hibernate.connection.driver_class">com.MysqL.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:MysqL://localhost:3306/gsui?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true</property>
<property name="hibernate.connection.autoReconnect">true</property>
<!-- C3p0 Performance Improvements -->
<property name="hibernate.c3p0.acquire_increment">1</property>
<property name="hibernate.c3p0.idle_test_period">300</property>
<property name="hibernate.c3p0.maxConnectionAge">3600</property>
<property name="hibernate.c3p0.timeout">120</property>
<property name="hibernate.c3p0.max_size">300</property>
<property name="hibernate.c3p0.min_size">1</property>
<property name="hibernate.c3p0.max_statements">100</property>
<property name="hibernate.c3p0.preferredTestQuery">select 1;</property>
<property name="hibernate.connection.useUnicode">
true
</property>
<property name="hibernate.connection.characterEncoding">
UTF-8
</property>
<property name="hibernate.connection.charSet">
UTF-8
</property>
我还在我维护的c3p0属性文件中将c3p0.testConnectionOnCheckout设置为true:
c3p0.testConnectionOnCheckout=true
在日志中,C3P0池使用以下消息初始化正常:
2013-01-27 19:45:04,607 INFO [main] (ConnectionProviderFactory.java:173) - Initializing connection provider: org.hibernate.connection.C3P0ConnectionProvider
2013-01-27 19:45:04,609 INFO [main] (C3P0ConnectionProvider.java:103) - C3P0 using driver: com.MysqL.jdbc.Driver at URL: jdbc:MysqL://localhost:3306/gsui?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true
2013-01-27 19:45:04,610 INFO [main] (C3P0ConnectionProvider.java:104) - Connection properties: {useUnicode=true, autoReconnect=true, user=root, password=****, shutdown=true, characterEncoding=UTF-8, charSet=UTF-8}
2013-01-27 19:45:04,610 INFO [main] (C3P0ConnectionProvider.java:107) - autocommit mode: false
2013-01-27 19:45:04,629 INFO [main] (MLog.java:80) - MLog clients using log4j logging.
2013-01-27 19:45:04,757 INFO [main] (C3P0Registry.java:204) - Initializing c3p0-0.9.1.2 [built 21-May-2007 15:04:56; debug? true; trace: 10]
2013-01-27 19:45:04,842 INFO [main] (C3P0ConnectionProvider.java:194) - JDBC isolation level: READ_COMMITTED
2013-01-27 19:45:04,871 INFO [main] (AbstractPoolBackedDataSource.java:462) - Initializing c3p0 pool... com.mchange.v2.c3p0.PoolBackedDataSource@9f4a7137 [ connectionPoolDataSource -> com.mchange.v2.c3p0.WrapperConnectionPoolDataSource@71b9e1e9 [ acquireIncrement -> 1, acquireRetryAttempts -> 30, acquireRetryDelay -> 1000, autoCommitOnClose -> false, automaticTestTable -> null, breakAfteracquireFailure -> false, checkoutTimeout -> 0, connectionCustomizerClassName -> null, connectionTesterClassName -> com.mchange.v2.c3p0.impl.DefaultConnectionTester, debugUnreturnedConnectionStackTraces -> false, factoryClassLocation -> null, forceIgnoreUnresolvedTransactions -> false, identityToken -> z8kfsx8sz4pted1s4b69w|51f726b9, idleConnectionTestPeriod -> 300, initialPoolSize -> 1, maxAdministrativeTasktime -> 0, maxConnectionAge -> 3600, maxIdleTime -> 120, maxIdleTimeExcessConnections -> 0, maxPoolSize -> 300, maxStatements -> 100, maxStatementsPerConnection -> 0, minPoolSize -> 1, nestedDataSource -> com.mchange.v2.c3p0.DriverManagerDataSource@58f45048 [ description -> null, driverClass -> null, factoryClassLocation -> null, identityToken -> z8kfsx8sz4pted1s4b69w|454b7177, jdbcUrl -> jdbc:MysqL://localhost:3306/gsui?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true, properties -> {useUnicode=true, autoReconnect=true, user=******, password=******, shutdown=true, characterEncoding=UTF-8, charSet=UTF-8} ], preferredTestQuery -> select 1;, propertyCycle -> 0, testConnectionOnCheckin -> false, testConnectionOnCheckout -> true, unreturnedConnectionTimeout -> 0, usesTraditionalReflectiveProxies -> false; userOverrides: {} ], dataSourceName -> null, factoryClassLocation -> null, identityToken -> z8kfsx8sz4pted1s4b69w|71ffd9f1, numHelperThreads -> 3 ]
从上面的日志中,可以发现C3P0中的testConnectionOnCheckout = true和autoReconnect = true.有人可以帮我弄清楚为什么C3P0会检出一个超时连接吗?谢谢.
解决方法:
当我们使用JPA和C3P0将hibernate升级到4.3.x以进行连接池时,我们开始遇到相同的“通信链接”问题.
这似乎是一个连接池问题,因为尽管我的C3P0设置,连接保持的时间比数据库wait_timeout(默认的8小时)长.但是,我通过使用以下命令更改persistence.xml中的hibernate配置来修复此问题:
<property name="hibernate.connection.release_mode" value="after_transaction" />
似乎hibernate中的默认行为更改为在事务之后不释放连接,因此如果您正在使用池,则必须显式设置此模式.
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。