mysql - C3P0 明显死锁

标签 mysql database-connection connection-pooling c3p0

我的服务器曾经在日志中看到 APPARENT DEADLOCK。我有几台服务器在负载平衡器后面运行,有趣的是我看到死锁同时发生在所有服务器上(有人知道为什么它会影响所有服务器)吗?。在此期间,通常需要 200 毫秒的 MySQL 查询需要 >60 秒。这是当时日志的样子:

com.mchange.v2.async.ThreadPoolAsynchronousRunner: com.mchange.v2.async.ThreadPoolAsynchronousRunner$DeadlockDetector@58780f76
 -- APPARENT DEADLOCK!!! Complete Status: 
        Managed Threads: 3
        Active Threads: 3
        Active Tasks: 
                com.mchange.v2.c3p0.stmt.GooGooStatementCache$1StatementCloseTask@25ff87d4 (com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#0)
                com.mchange.v2.c3p0.stmt.GooGooStatementCache$1StatementCloseTask@10ccf7ef (com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#1)
                com.mchange.v2.c3p0.stmt.GooGooStatementCache$1StatementCloseTask@3305ec37 (com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#2)
        Pending Tasks: 
                com.mchange.v2.c3p0.stmt.GooGooStatementCache$1StatementCloseTask@39cc9e5a
                com.mchange.v2.c3p0.stmt.GooGooStatementCache$1StmtAcquireTask@60d46f90
                com.mchange.v2.c3p0.stmt.GooGooStatementCache$1StatementCloseTask@17509fea
                com.mchange.v2.c3p0.stmt.GooGooStatementCache$1StatementCloseTask@b28bd63
                com.mchange.v2.c3p0.stmt.GooGooStatementCache$1StatementCloseTask@56cbdc12
                com.mchange.v2.c3p0.stmt.GooGooStatementCache$1StatementCloseTask@15a091b4
                com.mchange.v2.c3p0.stmt.GooGooStatementCache$1StatementCloseTask@61ce325
                com.mchange.v2.c3p0.stmt.GooGooStatementCache$1StmtAcquireTask@48119520
                com.mchange.v2.c3p0.stmt.GooGooStatementCache$1StatementCloseTask@4032fb7c
                com.mchange.v2.c3p0.stmt.GooGooStatementCache$1StmtAcquireTask@518eefff
                com.mchange.v2.c3p0.stmt.GooGooStatementCache$1StmtAcquireTask@30ea3b20
                com.mchange.v2.c3p0.stmt.GooGooStatementCache$1StmtAcquireTask@74960088
                com.mchange.v2.c3p0.stmt.GooGooStatementCache$1StmtAcquireTask@23a8fc7d
                com.mchange.v2.c3p0.stmt.GooGooStatementCache$1StmtAcquireTask@5ff0ee0
                com.mchange.v2.c3p0.stmt.GooGooStatementCache$1StatementCloseTask@642d0644
                com.mchange.v2.c3p0.stmt.GooGooStatementCache$1StatementCloseTask@207bc809
                com.mchange.v2.c3p0.stmt.GooGooStatementCache$1StatementCloseTask@44d4936f
                com.mchange.v2.c3p0.stmt.GooGooStatementCache$1StatementCloseTask@39a10d1b
                com.mchange.v2.c3p0.stmt.GooGooStatementCache$1StatementCloseTask@3532334d
                com.mchange.v2.c3p0.stmt.GooGooStatementCache$1StatementCloseTask@4bf79e62
                com.mchange.v2.c3p0.stmt.GooGooStatementCache$1StatementCloseTask@2bd83398
                com.mchange.v2.c3p0.stmt.GooGooStatementCache$1StmtAcquireTask@1a202a2d
                com.mchange.v2.c3p0.stmt.GooGooStatementCache$1StatementCloseTask@3eacda7f
                com.mchange.v2.c3p0.stmt.GooGooStatementCache$1StatementCloseTask@495f5746
                com.mchange.v2.c3p0.stmt.GooGooStatementCache$1StmtAcquireTask@23f1f906

所以我来到 Stack Overflow 和 found this answer which suggested我将 statementCacheNumDeferredCloseThreads 设置为 1。我这样做了,我看到 DEADLOCK 的频率降低了,而且只出现在负载均衡器后面的几台服务器上,而不是所有服务器上。

现在日志看起来有点不同,但是在 DEADLOCK 期间,查询仍然很长:

10 Oct 2018 06:33:32,037 [WARN]  (Timer-0) com.mchange.v2.async.ThreadPoolAsynchronousRunner: com.mchange.v2.async.ThreadPoolAsynchronousRunner$DeadlockDetector@4f39ad63 -- APPARENT DEADLOCK!!! Complete Status: 
        Managed Threads: 3
        Active Threads: 3
        Active Tasks: 
                com.mchange.v2.c3p0.stmt.GooGooStatementCache$1StatementCloseTask@34dee200 (com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#2)
                com.mchange.v2.c3p0.stmt.GooGooStatementCache$1StatementCloseTask@3727ee6b (com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#1)
                com.mchange.v2.c3p0.stmt.GooGooStatementCache$1StatementCloseTask@4afb8b9 (com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#0)
        Pending Tasks: 
                com.mchange.v2.c3p0.stmt.GooGooStatementCache$1StmtAcquireTask@384a3b5b
                com.mchange.v2.c3p0.stmt.GooGooStatementCache$1StmtAcquireTask@7bc700b0
                com.mchange.v2.resourcepool.BasicResourcePool$1RefurbishCheckinResourceTask@731bfd15
                com.mchange.v2.resourcepool.BasicResourcePool$1RefurbishCheckinResourceTask@a88e9bf
                com.mchange.v2.resourcepool.BasicResourcePool$1RefurbishCheckinResourceTask@63f18b56
                com.mchange.v2.resourcepool.BasicResourcePool$1RefurbishCheckinResourceTask@20f0c518
                com.mchange.v2.c3p0.stmt.GooGooStatementCache$1StmtAcquireTask@caf7746
                com.mchange.v2.resourcepool.BasicResourcePool$1RefurbishCheckinResourceTask@41a7a27d
                com.mchange.v2.resourcepool.BasicResourcePool$1RefurbishCheckinResourceTask@2ee32a24
                com.mchange.v2.c3p0.stmt.GooGooStatementCache$1StmtAcquireTask@81df2e5
                com.mchange.v2.resourcepool.BasicResourcePool$1RefurbishCheckinResourceTask@7f7fa1e7
                com.mchange.v2.resourcepool.BasicResourcePool$1RefurbishCheckinResourceTask@337503f
                com.mchange.v2.resourcepool.BasicResourcePool$1RefurbishCheckinResourceTask@34b2f877
                com.mchange.v2.c3p0.stmt.GooGooStatementCache$1StmtAcquireTask@53dfbede
                com.mchange.v2.c3p0.stmt.GooGooStatementCache$1StmtAcquireTask@512d5ddb
                com.mchange.v2.resourcepool.BasicResourcePool$1RefurbishCheckinResourceTask@68a25969
                com.mchange.v2.resourcepool.BasicResourcePool$1RefurbishCheckinResourceTask@4bf0754a
                com.mchange.v2.resourcepool.BasicResourcePool$1RefurbishCheckinResourceTask@65770ba4
                com.mchange.v2.resourcepool.BasicResourcePool$1RefurbishCheckinResourceTask@5e0f4154
                com.mchange.v2.c3p0.stmt.GooGooStatementCache$1StmtAcquireTask@249c22ed
                com.mchange.v2.resourcepool.BasicResourcePool$1RefurbishCheckinResourceTask@6c8e5911
                com.mchange.v2.c3p0.stmt.GooGooStatementCache$1StmtAcquireTask@3179550f
                com.mchange.v2.resourcepool.BasicResourcePool$1RefurbishCheckinResourceTask@15d8a795
                com.mchange.v2.c3p0.stmt.GooGooStatementCache$1StmtAcquireTask@50966489
                com.mchange.v2.resourcepool.BasicResourcePool$1RefurbishCheckinResourceTask@4ecee95b
                com.mchange.v2.c3p0.stmt.GooGooStatementCache$1StmtAcquireTask@35640ca0
                com.mchange.v2.resourcepool.BasicResourcePool$AsyncTestIdleResourceTask@6550f196
                com.mchange.v2.resourcepool.BasicResourcePool$AsyncTestIdleResourceTask@6816399
                com.mchange.v2.resourcepool.BasicResourcePool$AsyncTestIdleResourceTask@3fbcd623
Pool thread stack traces:
        Thread[com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#2,5,main]
                com.mysql.jdbc.PreparedStatement.realClose(PreparedStatement.java:2765)
                com.mysql.jdbc.StatementImpl.close(StatementImpl.java:541)
                com.mchange.v1.db.sql.StatementUtils.attemptClose(StatementUtils.java:41)
                com.mchange.v2.c3p0.stmt.GooGooStatementCache$1StatementCloseTask.run(GooGooStatementCache.java:404)
                com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread.run(ThreadPoolAsynchronousRunner.java:547)
        Thread[com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#1,5,main]
                com.mysql.jdbc.PreparedStatement.realClose(PreparedStatement.java:2765)
                com.mysql.jdbc.StatementImpl.close(StatementImpl.java:541)
                com.mchange.v1.db.sql.StatementUtils.attemptClose(StatementUtils.java:41)
                com.mchange.v2.c3p0.stmt.GooGooStatementCache$1StatementCloseTask.run(GooGooStatementCache.java:404)
                com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread.run(ThreadPoolAsynchronousRunner.java:547)
        Thread[com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#0,5,main]
                com.mysql.jdbc.PreparedStatement.realClose(PreparedStatement.java:2765)
                com.mysql.jdbc.StatementImpl.close(StatementImpl.java:541)
                com.mchange.v1.db.sql.StatementUtils.attemptClose(StatementUtils.java:41)
                com.mchange.v2.c3p0.stmt.GooGooStatementCache$1StatementCloseTask.run(GooGooStatementCache.java:404)
                com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread.run(ThreadPoolAsynchronousRunner.java:547)

知道如何解决这个问题吗?我可以尝试完全禁用语句缓存,但我担心总体性能受到影响。其他一些相关参数:

minPoolSize = 30
maxPoolSize = 30
maxStatements = 100
unreturnedConnectionTimeout = 500
idleConnectionTestPeriod = 60
acquireIncrements = 3
C3p0 version = 0.9.1.2

编辑:我忘了说,在我发现死锁较少的改进过程中,我还增加了 maxStatements,这可以解释改进。但是现在我只看到https://github.com/swaldman/c3p0/issues/53其中表示 version 0.9.2 引入了这个新参数 statementCacheNumDeferredCloseThreads。我的版本太旧了。我没有收到关于此参数不存在的警告/错误。

最佳答案

也许为时已晚,但您是否尝试过增加 numHelperThreads 的数量?

关于mysql - C3P0 明显死锁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52742651/

相关文章:

php - PDO 对象 :could not find driver

java - 表名是什么?

mysql - Zend数据库连接失败

c# - 如何将 Blazor WebAssembly 连接到数据库

python - 将 pycassa 与 uwsgi 一起使用时的问题

c++ - 通过 C++ 连接到 mySQL

c# - 如何添加到表格单元格而不覆盖数据?

mysql - 随产品附带 MYSQL 数据库

java - 每个线程的新连接实例上的连接池 (JDBC)

database - 服务器无法连接到 pgbouncer (PostgreSQL)