我在我的网络应用程序中使用Hibernate与c3p0结合使用(NO Spring)。
一夜之间,我的数据库连接似乎超时(或至少其中一个),第二天我得到了一个破损的管道异常。
以下是我用于项目的配置。
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/**********?autoReconnect=true</property>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.dialect">org.hibernate.dialect.MySQLInnoDBDialect</property>
<property name="hibernate.connection.username">********</property>
<property name="hibernate.connection.password">********</property>
<property name="hibernate.show_sql">false</property>
<property name="hibernate.globally_quoted_identifiers">true</property>
<property name="hibernate.current_session_context_class">thread</property>
<property name="hibernate.transaction.factory_class">org.hibernate.transaction.JDBCTransactionFactory</property>
<property name="hibernate.connection.autocommit">false</property>
<property name="hibernate.connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</property>
<property name="hibernate.c3p0.min_size">5</property>
<property name="hibernate.c3p0.max_size">25</property>
<property name="hibernate.c3p0.timeout">300</property>
<property name="hibernate.c3p0.max_statements">50</property>
<property name="hibernate.c3p0.idle_test_period">60</property>
<property name="hibernate.c3p0.acquire_increment">1</property>
<property name="hibernate.c3p0.acquireRetryAttempts">5</property>
<property name="hibernate.c3p0.acquireRetryDelay">250</property>
<property name="hibernate.c3p0.preferredTestQuery">select 1;</property>
<property name="hibernate.c3p0.validate">true</property>
<property name="hibernate.c3p0.testConnectionOnCheckout">true</property>
<property name="hibernate.c3p0.testConnectionOnCheckin">true</property>
</session-factory>
</hibernate-configuration>
例外情况我看起来如下:
The last packet successfully received from the server was 56,974,967 milliseconds ago. The last packet sent successfully to the server was 56,974,967 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. org.hibernate.exception.JDBCConnectionException: The last packet successfully received from the server was 56,974,967 milliseconds ago. The last packet sent successfully to the server was 56,974,967 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.
这里的问题是,我使用属性autoReconnect = true,我正在测试连接有效性。 (请参阅c3p0配置。)我非常确定已加载c3p0配置,因为以下内容显示在我的stdout日志中:
Apr 08, 2014 10:57:13 AM com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource getPoolManager INFO: Initializing c3p0 pool... com.mchange.v2.c3p0.PoolBackedDataSource@f79fb235 [ connectionPoolDataSource -> com.mchange.v2.c3p0.WrapperConnectionPoolDataSource@4e20d034 [ acquireIncrement -> 1, acquireRetryAttempts -> 5, acquireRetryDelay -> 250, autoCommitOnClose -> false, automaticTestTable -> null, breakAfterAcquireFailure -> false, checkoutTimeout -> 0, connectionCustomizerClassName -> null, connectionTesterClassName -> com.mchange.v2.c3p0.impl.DefaultConnectionTester, debugUnreturnedConnectionStackTraces -> false, factoryClassLocation -> null, forceIgnoreUnresolvedTransactions -> false, identityToken -> ph9ube91hyyxjw1mgbhpo|709689fb, idleConnectionTestPeriod -> 60, initialPoolSize -> 3, maxAdministrativeTaskTime -> 0, maxConnectionAge -> 0, maxIdleTime -> 300, maxIdleTimeExcessConnections -> 0, maxPoolSize -> 25, maxStatements -> 50, maxStatementsPerConnection -> 0, minPoolSize -> 5, nestedDataSource -> com.mchange.v2.c3p0.DriverManagerDataSource@a1ca3a3 [ description -> null, driverClass -> null, factoryClassLocation -> null, identityToken -> ph9ube91hyyxjw1mgbhpo|24bbab7, jdbcUrl -> jdbc:mysql://localhost:3306/********?autoReconnect=true, properties -> {user=******, password=******, autocommit=false} ], preferredTestQuery -> select 1;, propertyCycle -> 0, testConnectionOnCheckin -> true, testConnectionOnCheckout -> true, unreturnedConnectionTimeout -> 0, usesTraditionalReflectiveProxies -> false; userOverrides: {} ], dataSourceName -> null, factoryClassLocation -> null, identityToken -> ph9ube91hyyxjw1mgbhpo|fedb05d, numHelperThreads -> 3 ]
例外的破损管道部分是:
Caused by: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: The last packet successfully received from the server was 56,974,967 milliseconds ago. The last packet sent successfully to the server was 56,974,967 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(NativeConstructorAccessorImpl.java:57) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) at java.lang.reflect.Constructor.newInstance(Constructor.java:525) 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:3851) at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2471) at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2651) at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2683) at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:2144) at com.mysql.jdbc.PreparedStatement.executeQuery(PreparedStatement.java:2310) at com.mchange.v2.c3p0.impl.NewProxyPreparedStatement.executeQuery(NewProxyPreparedStatement.java:76) at sun.reflect.GeneratedMethodAccessor35.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:601) at org.hibernate.engine.jdbc.internal.proxy.AbstractStatementProxyHandler.continueInvocation(AbstractStatementProxyHandler.java:122) ... 23 more Caused by: java.net.SocketException: Broken pipe at java.net.SocketOutputStream.socketWrite0(Native Method) at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:109) at java.net.SocketOutputStream.write(SocketOutputStream.java:153) at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:82) at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:140) at com.mysql.jdbc.MysqlIO.send(MysqlIO.java:3832) ... 33 more
我根据我在互联网上找到的内容尝试了以下内容:
似乎没有任何效果。有没有人知道可能导致这个问题的原因?
答案 0 :(得分:2)
所以,一些散射的想法:
preferredTestQuery
出现错误。它应该是“SELECT 1”而不是“SELECT 1;”。我认为如果这是一个问题,你会看到它的例外(并且结账都会失败),但值得尝试解决这个问题。
[您使用的是什么版本的c3p0?如果你想危险地生活并使用最新的MySQL驱动程序,请尝试使用最新的预发行版,目前是c3p0-0.9.5-pre8,而根本不设置preferredTestQuery
。最新版本支持JDBC4 Connection.isValid()进行测试。]
另一种可能性是您的应用程序偶尔会将Connections打开(签出)很长时间。这不会是一个Connection泄漏,因为最终应用程序尝试对Connection执行一个Statement。但是如果您的应用程序执行此操作,您将看到您所看到的内容,因为c3p0在客户端使用时不会测试Connections,因此他们可以闲置。 (我不知道为什么autoReconnect没有帮助,除非你处于事务中期并且autoReconnect不起作用?)如果你想测试这个场景,你可以使用unreturnedConnectionTimeout(可选) debugUnreturnedConnectionStackTraces)强行关闭过长检查的异常并尝试诊断问题。
如果您只是希望问题消失(并且不太关心理解它),您也可以尝试设置c3p0的maxConnectionAge和/或maxIdleTime。如果将这些设置为较大值,则这些设置不会对性能产生重大影响。 (可能是7200秒,即两个小时,但超过1800秒就可以了。)这些设置(尤其是maxConnectionAge)非常简单,除非麻烦的连接在上面保持打开状态并从池中检出很长时间。 [唯一的c3p0设置将关闭()从客户端下面检出的连接是unreturnedConnectionTimeout
。]