Java / Hibernate在客户端重新连接

时间:2014-12-06 19:08:16

标签: java mysql hibernate jpa c3p0

我有一个24/7运行的mysql服务器和许多使用JP​​A / Hibernate访问数据库的SWT富客户端......

如果客户端计算机(笔记本电脑)进入休眠/待机状态并在一段时间后唤醒数据库连接丢失 - 无论何种设置和/或数据库连接提供程序(我试过c3p0和vibur)我都使用....

这是我当前的hibernate.xml属性文件(也不起作用)......:

    <property name="connection.pool_size">3</property>
    <property name="cache.provider_class">org.hibernate.cache.EhCacheProvider</property>
    <property name="hibernate.cache.use_query_cache">false</property>

    <property name="hibernate.current_session_context_class">thread</property>

    <property name="hibernate.c3p0.validate">true</property>
    <property name="hibernate.connection.provider_class">org.hibernate.service.jdbc.connections.internal.C3P0ConnectionProvider</property>
    <property name="hibernate.c3p0.min_size">5</property>
    <property name="hibernate.c3p0.max_size">600</property>
    <property name="hibernate.c3p0.timeout">0</property>
    <property name="hibernate.c3p0.max_statements">50</property>
    <property name="hibernate.c3p0.preferredTestQuery">SELECT 1;</property>
    <property name="hibernate.c3p0.testConnectionOnCheckout">true</property>
    <property name="hibernate.c3p0.testConnectionOnCheckin">true</property>
            <property name="hibernate.c3p0.idle_test_period">3000</property>
    <property name="hibernate.c3p0.acquireRetryAttempts">10</property>
    <property name="hibernate.c3p0.acquireRetryDelay">1000</property>
    <property name="hibernate.c3p0.breakAfterAcquireFailure">false</property>

这是一个错误堆栈跟踪:

WARN | 02.12.2014 21:35:06,503 | [C3P0PooledConnectionPoolManager[identityToken->1hge13a96372xk9xvyjyj|1dd3180]-AdminTaskTimer] | ThreadPoolAsynchronousRunner:743 | com.mchange.v2.async.ThreadPoolAsynchronousRunner$DeadlockDetector@89789 -- APPARENT DEADLOCK!!! Creating emergency threads for unassigned pending tasks!
 WARN | 02.12.2014 21:35:06,507 | [C3P0PooledConnectionPoolManager[identityToken->1hge13a96372xk9xvyjyj|1dd3180]-AdminTaskTimer] | ThreadPoolAsynchronousRunner:759 | com.mchange.v2.async.ThreadPoolAsynchronousRunner$DeadlockDetector@89789 -- APPARENT DEADLOCK!!! Complete Status: 
    Managed Threads: 3
    Active Threads: 3
    Active Tasks: 
        com.mchange.v2.resourcepool.BasicResourcePool$ScatteredAcquireTask@b76a87
            on thread: C3P0PooledConnectionPoolManager[identityToken->1hge13a96372xk9xvyjyj|1dd3180]-HelperThread-#0
        com.mchange.v2.resourcepool.BasicResourcePool$ScatteredAcquireTask@1b2ffe7
            on thread: C3P0PooledConnectionPoolManager[identityToken->1hge13a96372xk9xvyjyj|1dd3180]-HelperThread-#1
        com.mchange.v2.resourcepool.BasicResourcePool$ScatteredAcquireTask@becbe1
            on thread: C3P0PooledConnectionPoolManager[identityToken->1hge13a96372xk9xvyjyj|1dd3180]-HelperThread-#2
    Pending Tasks: 
        com.mchange.v2.resourcepool.BasicResourcePool$ScatteredAcquireTask@3b2d78
Pool thread stack traces:
    Thread[C3P0PooledConnectionPoolManager[identityToken->1hge13a96372xk9xvyjyj|1dd3180]-HelperThread-#0,5,main]
        java.net.DualStackPlainSocketImpl.connect0(Native Method)
        java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:79)
        java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:339)
        java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:200)
        java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:182)
        java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172)
        java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
        java.net.Socket.connect(Socket.java:579)
        java.net.Socket.connect(Socket.java:528)
        java.net.Socket.<init>(Socket.java:425)
        java.net.Socket.<init>(Socket.java:241)
        com.mysql.jdbc.StandardSocketFactory.connect(StandardSocketFactory.java:259)
        com.mysql.jdbc.MysqlIO.<init>(MysqlIO.java:307)
        com.mysql.jdbc.ConnectionImpl.coreConnect(ConnectionImpl.java:2482)
        com.mysql.jdbc.ConnectionImpl.connectOneTryOnly(ConnectionImpl.java:2519)
        com.mysql.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:2304)
        com.mysql.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:834)
        com.mysql.jdbc.JDBC4Connection.<init>(JDBC4Connection.java:47)
        sun.reflect.GeneratedConstructorAccessor249.newInstance(Unknown Source)
        sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
        java.lang.reflect.Constructor.newInstance(Constructor.java:526)
        com.mysql.jdbc.Util.handleNewInstance(Util.java:411)
        com.mysql.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:416)
        com.mysql.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:346)
        com.mchange.v2.c3p0.DriverManagerDataSource.getConnection(DriverManagerDataSource.java:146)
        com.mchange.v2.c3p0.WrapperConnectionPoolDataSource.getPooledConnection(WrapperConnectionPoolDataSource.java:195)
        com.mchange.v2.c3p0.WrapperConnectionPoolDataSource.getPooledConnection(WrapperConnectionPoolDataSource.java:184)
        com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool$1PooledConnectionResourcePoolManager.acquireResource(C3P0PooledConnectionPool.java:200)
        com.mchange.v2.resourcepool.BasicResourcePool.doAcquire(BasicResourcePool.java:1086)
        com.mchange.v2.resourcepool.BasicResourcePool.doAcquireAndDecrementPendingAcquiresWithinLockOnSuccess(BasicResourcePool.java:1073)
        com.mchange.v2.resourcepool.BasicResourcePool.access$800(BasicResourcePool.java:44)
        com.mchange.v2.resourcepool.BasicResourcePool$ScatteredAcquireTask.run(BasicResourcePool.java:1810)
        com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread.run(ThreadPoolAsynchronousRunner.java:648)
    Thread[C3P0PooledConnectionPoolManager[identityToken->1hge13a96372xk9xvyjyj|1dd3180]-HelperThread-#2,5,main]
        java.net.DualStackPlainSocketImpl.connect0(Native Method)
        java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:79)
        java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:339)
        java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:200)
        java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:182)
        java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172)
        java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
        java.net.Socket.connect(Socket.java:579)
        java.net.Socket.connect(Socket.java:528)
        java.net.Socket.<init>(Socket.java:425)
        java.net.Socket.<init>(Socket.java:241)
        com.mysql.jdbc.StandardSocketFactory.connect(StandardSocketFactory.java:259)
        com.mysql.jdbc.MysqlIO.<init>(MysqlIO.java:307)
        com.mysql.jdbc.ConnectionImpl.coreConnect(ConnectionImpl.java:2482)
        com.mysql.jdbc.ConnectionImpl.connectOneTryOnly(ConnectionImpl.java:2519)
        com.mysql.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:2304)
        com.mysql.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:834)
        com.mysql.jdbc.JDBC4Connection.<init>(JDBC4Connection.java:47)
        sun.reflect.GeneratedConstructorAccessor249.newInstance(Unknown Source)
        sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
        java.lang.reflect.Constructor.newInstance(Constructor.java:526)
        com.mysql.jdbc.Util.handleNewInstance(Util.java:411)
        com.mysql.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:416)
        com.mysql.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:346)
        com.mchange.v2.c3p0.DriverManagerDataSource.getConnection(DriverManagerDataSource.java:146)
        com.mchange.v2.c3p0.WrapperConnectionPoolDataSource.getPooledConnection(WrapperConnectionPoolDataSource.java:195)
        com.mchange.v2.c3p0.WrapperConnectionPoolDataSource.getPooledConnection(WrapperConnectionPoolDataSource.java:184)
        com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool$1PooledConnectionResourcePoolManager.acquireResource(C3P0PooledConnectionPool.java:200)
        com.mchange.v2.resourcepool.BasicResourcePool.doAcquire(BasicResourcePool.java:1086)
        com.mchange.v2.resourcepool.BasicResourcePool.doAcquireAndDecrementPendingAcquiresWithinLockOnSuccess(BasicResourcePool.java:1073)
        com.mchange.v2.resourcepool.BasicResourcePool.access$800(BasicResourcePool.java:44)
        com.mchange.v2.resourcepool.BasicResourcePool$ScatteredAcquireTask.run(BasicResourcePool.java:1810)
        com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread.run(ThreadPoolAsynchronousRunner.java:648)
    Thread[C3P0PooledConnectionPoolManager[identityToken->1hge13a96372xk9xvyjyj|1dd3180]-HelperThread-#1,5,main]
        java.net.DualStackPlainSocketImpl.connect0(Native Method)
        java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:79)
        java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:339)
        java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:200)
        java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:182)
        java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172)
        java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
        java.net.Socket.connect(Socket.java:579)
        java.net.Socket.connect(Socket.java:528)
        java.net.Socket.<init>(Socket.java:425)
        java.net.Socket.<init>(Socket.java:241)
        com.mysql.jdbc.StandardSocketFactory.connect(StandardSocketFactory.java:259)
        com.mysql.jdbc.MysqlIO.<init>(MysqlIO.java:307)
        com.mysql.jdbc.ConnectionImpl.coreConnect(ConnectionImpl.java:2482)
        com.mysql.jdbc.ConnectionImpl.connectOneTryOnly(ConnectionImpl.java:2519)
        com.mysql.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:2304)
        com.mysql.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:834)
        com.mysql.jdbc.JDBC4Connection.<init>(JDBC4Connection.java:47)
        sun.reflect.GeneratedConstructorAccessor249.newInstance(Unknown Source)
        sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
        java.lang.reflect.Constructor.newInstance(Constructor.java:526)
        com.mysql.jdbc.Util.handleNewInstance(Util.java:411)
        com.mysql.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:416)
        com.mysql.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:346)
        com.mchange.v2.c3p0.DriverManagerDataSource.getConnection(DriverManagerDataSource.java:146)
        com.mchange.v2.c3p0.WrapperConnectionPoolDataSource.getPooledConnection(WrapperConnectionPoolDataSource.java:195)
        com.mchange.v2.c3p0.WrapperConnectionPoolDataSource.getPooledConnection(WrapperConnectionPoolDataSource.java:184)
        com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool$1PooledConnectionResourcePoolManager.acquireResource(C3P0PooledConnectionPool.java:200)
        com.mchange.v2.resourcepool.BasicResourcePool.doAcquire(BasicResourcePool.java:1086)
        com.mchange.v2.resourcepool.BasicResourcePool.doAcquireAndDecrementPendingAcquiresWithinLockOnSuccess(BasicResourcePool.java:1073)
        com.mchange.v2.resourcepool.BasicResourcePool.access$800(BasicResourcePool.java:44)
        com.mchange.v2.resourcepool.BasicResourcePool$ScatteredAcquireTask.run(BasicResourcePool.java:1810)
        com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread.run(ThreadPoolAsynchronousRunner.java:648)


 WARN | 03.12.2014 10:29:20,014 | [main] | SqlExceptionHelper:145 | SQL Error: 0, SQLState: 08S01
ERROR | 03.12.2014 10:29:20,015 | [main] | SqlExceptionHelper:147 | The last packet successfully received from the server was 65.896.659 milliseconds ago.  The last packet sent successfully to the server was 65.896.672 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.

3 个答案:

答案 0 :(得分:0)

当数据库服务器(或笔记本电脑客户端)出现故障时,正在获取新数据库连接的线程卡住了。他们是DBMS的中间通信,只是悬挂。它们既没有成功获取连接,也没有及时处理异常。这些挂起的线程使您的线程池饱和,从而阻止完成各种任务。一段时间后,c3p0声明一个APPARENT DEADLOCK !,然后丢弃并替换其线程池中的所有线程重新开始。通常应用程序在APPARENT DEADLOCK后恢复并正常运行!但是,如果由于中断而中断的Connection尝试既没有成功也没有因异常而失败,您可能偶尔会看到这些死锁。

有些事情可能会有所帮助。如果连接获取尝试被卡住的I / O操作是可中断的,则可以通过设置maxAdministrativeTaskTime来阻止APPARENT DEADLOCKS。但是,如果I / O不可中断,那将无法工作。

如果您经常看到这些死锁,那可能意味着您过快地通过Connections进行搅拌。在经过良好调整的池中,连接获取尝试应该是非常罕见的,因此在多次采集中发生中断也应该是非常罕见的。上面的配置中没有任何内容可以导致你通过Connections流失,但你说你引用的配置“不起作用”,所以也许真正的c3p0配置是不同的。 c3p0 DataSource将其配置转储到池初始化,在INFO级别。如果您搜索日志,则可以验证您想要的配置是否实际上是您的c3p0数据源的配置。

答案 1 :(得分:0)

由于它们都挂在连接上,因此请尝试为MySQL JDBC驱动程序设置connectTimeout(在MySQL connector J documentation中提及)。默认情况下,没有超时可能会让它们永远挂起。

进入待机状态并唤醒是您应该在客户端应用程序中捕获的内容,以便您可以采取措施来防止错误(例如,关闭数据库连接然后打开新的连接)。请参阅this answer,了解如何捕获某些类型的事件,遗憾的是,答案中不包含WM_POWERBROADCAST事件(在Windows上)的示例,该事件似乎表示待机/唤醒。我找到了一篇关于StandByDetector for Windows(YMMV)的文章。

当你在这里时,你可能想尝试HikariCP数据库连接池而不是c3p0(我怀疑HikariCP更好地从破碎的数据库连接中恢复)。您可以浏览setup-demo HibHik以开始使用。

答案 2 :(得分:0)

尝试HikariCP。 See our DB-down torture test。这仅适用于支持Connection.setNetworkTimeout()的优秀现代驱动程序。