Hibernate c3p0保持活力似乎不起作用,得到了“断管”#39;例外

时间:2014-04-09 09:35:39

标签: mysql hibernate c3p0 keep-alive broken-pipe

我在我的网络应用程序中使用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

我根据我在互联网上找到的内容尝试了以下内容:

  • 将autoReconnect = true添加到连接URL(请注意,尝试使用后连接仍然断开,因此似乎没有重新连接)
  • 将testConnectionOnCheckout和testConnectionOnCheckin添加到c3p0配置
  • 将idle_test_period和preferredTestQuery添加到c3p0 config

似乎没有任何效果。有没有人知道可能导致这个问题的原因?

1 个答案:

答案 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。]

祝你好运!