Как справиться с тупиковой ситуацией в спящем режиме? (c3p0)

Когда DEADLOCK распознается гибернацией DeadlockDetector (com.mchange.v2.async.ThreadPoolAsynchronousRunner $ DeadlockDetector) и SQL ERROR 1205 (Тайм-аут ожидания блокировки) неоднократно, все потоки c3p0 зависали, и приложение с дырой зависало.
I Меня не интересуют решения, позволяющие избежать самого тупика, а возможности программно отреагировать на это.

В этом случае какое-то другое приложение произвело блокировку таблицы на сервере базы данных. После того, как я убил приложение (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
hibernate: 5.0.0.CR1
Spring вообще не задействован.

полная трассировка стека:

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

person Marcus Thiel    schedule 12.04.2019    source источник
comment
APPARENT DEADLOCK должен распечатать дамп того, какие задачи заблокированы. Это полезно для отладки. Пожалуйста, добавьте это, если можете.   -  person Steve Waldman    schedule 14.04.2019
comment
Я добавил следы стека, отредактировав сообщение   -  person Marcus Thiel    schedule 15.04.2019


Ответы (1)


Из APPARENT DEADLOCK дампа данных ясно, что вы испытываете взаимоблокировки из-за попыток закрыть замораживание кешированных операторов. Это известная проблема / хрупкость в отношении взаимодействия кэширования операторов c3p0 и некоторых (особенно Oracle и jTDS) драйверов JDBC.

Есть два способа решить эту проблему. Самый простой - отключить кеширование операторов: убедитесь, что параметры конфигурации c3p0 maxStatements и maxStatementsPerConnection оба установлены в ноль.

Если вы получаете преимущества в производительности, которых хотите избежать от кэширования операторов, c3p0 имеет параметр , чтобы обойти его этот выпуск. TL; DR: добавьте свойство конфигурации c3p0 c3p0.statementCacheNumDeferredCloseThreads=1

person Steve Waldman    schedule 15.04.2019