如何处理休眠死锁? (c3p0)

时间:2019-04-12 14:36:35

标签: hibernate c3p0 database-deadlocks

当DEADLOCK被冬眠的DeadlockDetector(com.mchange.v2.async.ThreadPoolAsynchronousRunner $ DeadlockDetector)和SQL错误1205(锁定等待超时)反复识别时,c3p0的所有线程都被卡住,并且hole应用程序冻结。 /> 我对避免死锁本身的解决方案不感兴趣,但有可能以编程方式对此做出反应。

在这种情况下,其他一些应用程序在数据库服务器上产生了表锁。 在终止应用程序(SIGKILL)并重新启动之后,一切都很好。

APPARENT DEADLOCK!!! Creating emergency threads for unassigned pending tasks!
SQL Error: 1205, SQLState: 40001
Lock wait timeout exceeded; try restarting transaction

使用的版本:
c3p0:0.9.5.2
休眠状态:5.0.0.CR1
完全没有春天。

完整堆栈跟踪:

2019-04-12 15:04:27,102 [WARN ] Slf4jMLog$Slf4jMLogger$WarnLogger (C3P0PooledConnectionPoolManager[identityToken->2s35s8a24vskkqigquy5|31304f14]-AdminTaskTimer) - com.mchange.v2.async.ThreadPoolAsynchronousRunner$DeadlockDetector@4d710599 -- APPARENT DEADLOCK!!! Creating
emergency threads for unassigned pending tasks!
2019-04-12 15:04:27,104 [WARN ] Slf4jMLog$Slf4jMLogger$WarnLogger (C3P0PooledConnectionPoolManager[identityToken->2s35s8a24vskkqigquy5|31304f14]-AdminTaskTimer) - com.mchange.v2.async.ThreadPoolAsynchronousRunner$DeadlockDetector@4d710599 -- APPARENT DEADLOCK!!! Complete
Status:
Managed Threads: 3
Active Threads: 3
Active Tasks:
com.mchange.v2.c3p0.stmt.GooGooStatementCache$StatementDestructionManager$1UncheckedStatementCloseTask@679ab26c
on thread: C3P0PooledConnectionPoolManager[identityToken->2s35s8a24vskkqigquy5|31304f14]-HelperThread-#2
com.mchange.v2.c3p0.stmt.GooGooStatementCache$StatementDestructionManager$1UncheckedStatementCloseTask@c9f62bd
on thread: C3P0PooledConnectionPoolManager[identityToken->2s35s8a24vskkqigquy5|31304f14]-HelperThread-#0
com.mchange.v2.c3p0.stmt.GooGooStatementCache$StatementDestructionManager$1UncheckedStatementCloseTask@6250fbb8
on thread: C3P0PooledConnectionPoolManager[identityToken->2s35s8a24vskkqigquy5|31304f14]-HelperThread-#1
Pending Tasks:
com.mchange.v2.c3p0.stmt.GooGooStatementCache$StatementDestructionManager$1UncheckedStatementCloseTask@4cdc18cd
com.mchange.v2.resourcepool.BasicResourcePool$1RefurbishCheckinResourceTask@7ee7dae8
com.mchange.v2.resourcepool.BasicResourcePool$1RefurbishCheckinResourceTask@99ac503
com.mchange.v2.c3p0.stmt.GooGooStatementCache$1StmtAcquireTask@6cf272b3
com.mchange.v2.resourcepool.BasicResourcePool$1RefurbishCheckinResourceTask@40c40590
com.mchange.v2.resourcepool.BasicResourcePool$1RefurbishCheckinResourceTask@34b7fa
com.mchange.v2.resourcepool.BasicResourcePool$1RefurbishCheckinResourceTask@5f59d822
com.mchange.v2.resourcepool.BasicResourcePool$1RefurbishCheckinResourceTask@20414e90

Pool thread stack traces:

Thread[C3P0PooledConnectionPoolManager[identityToken->2s35s8a24vskkqigquy5|31304f14]-HelperThread-#2,5,main]
com.mysql.jdbc.PreparedStatement.realClose(PreparedStatement.java:2689)
com.mysql.jdbc.StatementImpl.close(StatementImpl.java:534)
com.mchange.v1.db.sql.StatementUtils.attemptClose(StatementUtils.java:53)
com.mchange.v2.c3p0.stmt.GooGooStatementCache$StatementDestructionManager$1UncheckedStatementCloseTask.run(GooGooStatementCache.java:934)
com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread.run(ThreadPoolAsynchronousRunner.java:696)

Thread[C3P0PooledConnectionPoolManager[identityToken->2s35s8a24vskkqigquy5|31304f14]-HelperThread-#0,5,main]
com.mysql.jdbc.PreparedStatement.realClose(PreparedStatement.java:2689)
com.mysql.jdbc.StatementImpl.close(StatementImpl.java:534)
com.mchange.v1.db.sql.StatementUtils.attemptClose(StatementUtils.java:53)
com.mchange.v2.c3p0.stmt.GooGooStatementCache$StatementDestructionManager$1UncheckedStatementCloseTask.run(GooGooStatementCache.java:934)
com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread.run(ThreadPoolAsynchronousRunner.java:696)

Thread[C3P0PooledConnectionPoolManager[identityToken->2s35s8a24vskkqigquy5|31304f14]-HelperThread-#1,5,main]
com.mysql.jdbc.PreparedStatement.realClose(PreparedStatement.java:2689)
com.mysql.jdbc.StatementImpl.close(StatementImpl.java:534)
com.mchange.v1.db.sql.StatementUtils.attemptClose(StatementUtils.java:53)
com.mchange.v2.c3p0.stmt.GooGooStatementCache$StatementDestructionManager$1UncheckedStatementCloseTask.run(GooGooStatementCache.java:934)
com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread.run(ThreadPoolAsynchronousRunner.java:696)

    #tread 1
2019-04-12 15:04:28,795 [WARN ] SqlExceptionHelper (qtp1548271808-41) - SQL Error: 1205, SQLState: 40001
2019-04-12 15:04:28,797 [ERROR] SqlExceptionHelper (qtp1548271808-41) - Lock wait timeout exceeded; try restarting transaction
    #tread 2
2019-04-12 15:05:18,799 [WARN ] SqlExceptionHelper (qtp1548271808-23) - SQL Error: 1205, SQLState: 40001
2019-04-12 15:05:18,800 [ERROR] SqlExceptionHelper (qtp1548271808-23) - Lock wait timeout exceeded; try restarting transaction
    #tread 3
2019-04-12 15:05:18,799 [WARN ] SqlExceptionHelper (qtp1548271808-22) - SQL Error: 1205, SQLState: 40001
2019-04-12 15:05:18,801 [ERROR] SqlExceptionHelper (qtp1548271808-22) - Lock wait timeout exceeded; try restarting transaction

1 个答案:

答案 0 :(得分:0)

APPARENT DEADLOCK数据转储中可以明显看出,由于试图关闭冻结的冻结语句而导致了死锁。关于c3p0语句缓存与某些JDBC驱动程序(尤其是Oracle和jTDS)的交互,这是一个已知问题/脆弱性。

有两种方法可以解决此问题。最简单的一种是禁用语句缓存:确保c3p0配置参数maxStatementsmaxStatementsPerConnection都设置为零。

如果您希望保留语句缓存带来的性能优势,则c3p0具有setting to work around this issue TL; DR::添加c3p0配置属性c3p0.statementCacheNumDeferredCloseThreads=1