Java se 应用程序上的 C3P0 死锁

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/41684529/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 06:03:18  来源:igfitidea点击:

DEADLOCK with C3P0 on java se application

javasql-servermultithreadingthreadpoolc3p0

提问by Ska?

I encountered a critical problem with the c3p0 library (version 0.9.5.2) that I use in my Java SE application.

我在 Java SE 应用程序中使用的 c3p0 库(版本 0.9.5.2)遇到了一个严重问题。

My application uses a Thread Pool to parallelize task by executing jobs.

我的应用程序使用线程池通过执行作业来并行化任务。

Each job uses the database to read, update or delete data at least once up to (in very rare cases but it can happen) more than 10,000 times.

每个作业使用数据库读取、更新或删除数据至少一次,最多(在极少数情况下,但可能发生)超过 10,000 次。

I therefore included in my project c3p0 library to have a connection pool to the database so that all workers in my thread pool can simultaneously interact with it.

因此,我在我的项目 c3p0 库中包含了一个到数据库的连接池,以便我的线程池中的所有工作人员可以同时与其交互。

I do not have any problems when running my application on my development environment (OSX 10.11), but when I run it in production (Linux Debian 8) I encounter a big problem ! Indeed it freezes....

在我的开发环境 (OSX 10.11) 上运行我的应用程序时我没有任何问题,但是当我在生产环境 (Linux Debian 8) 中运行它时,我遇到了一个大问题!确实冻结了....

At first it was a deadlock with the following trace stack:

起初它是一个带有以下跟踪堆栈的死锁:

[WARNING] com.mchange.v2.async.ThreadPoolAsynchronousRunner$DeadlockDetector@479d237b -- APPARENT DEADLOCK!!! Creating emergency threads for unassigned pending tasks!
[WARNING] com.mchange.v2.async.ThreadPoolAsynchronousRunner$DeadlockDetector@479d237b -- APPARENT DEADLOCK!!! Complete Status: 
    Managed Threads: 3
    Active Threads: 3
    Active Tasks: 
        com.mchange.v2.resourcepool.BasicResourcePool$ScatteredAcquireTask@264fb34f
            on thread: C3P0PooledConnectionPoolManager[identityToken->z8kfsx9l1adv4kd1qtfdi6|659f3099]-HelperThread-#2
        com.mchange.v2.resourcepool.BasicResourcePool$ScatteredAcquireTask@39a5576b
            on thread: C3P0PooledConnectionPoolManager[identityToken->z8kfsx9l1adv4kd1qtfdi6|659f3099]-HelperThread-#1
        com.mchange.v2.resourcepool.BasicResourcePool$ScatteredAcquireTask@5e676544
            on thread: C3P0PooledConnectionPoolManager[identityToken->z8kfsx9l1adv4kd1qtfdi6|659f3099]-HelperThread-#0
    Pending Tasks: 
        com.mchange.v2.resourcepool.BasicResourcePool$ScatteredAcquireTask@6848208c
Pool thread stack traces:
    Thread[C3P0PooledConnectionPoolManager[identityToken->z8kfsx9l1adv4kd1qtfdi6|659f3099]-HelperThread-#2,5,main]
        sun.nio.ch.EPollArrayWrapper.epollWait(Native Method)
        sun.nio.ch.EPollArrayWrapper.poll(EPollArrayWrapper.java:269)
        sun.nio.ch.EPollSelectorImpl.doSelect(EPollSelectorImpl.java:93)
        sun.nio.ch.SelectorImpl.lockAndDoSelect(SelectorImpl.java:86)
        sun.nio.ch.SelectorImpl.select(SelectorImpl.java:97)
        com.microsoft.sqlserver.jdbc.SocketFinder.findSocketUsingJavaNIO(IOBuffer.java:2438)
        com.microsoft.sqlserver.jdbc.SocketFinder.findSocket(IOBuffer.java:2290)
        com.microsoft.sqlserver.jdbc.TDSChannel.open(IOBuffer.java:551)
        com.microsoft.sqlserver.jdbc.SQLServerConnection.connectHelper(SQLServerConnection.java:1962)
        com.microsoft.sqlserver.jdbc.SQLServerConnection.login(SQLServerConnection.java:1627)
        com.microsoft.sqlserver.jdbc.SQLServerConnection.connectInternal(SQLServerConnection.java:1458)
        com.microsoft.sqlserver.jdbc.SQLServerConnection.connect(SQLServerConnection.java:772)
        com.microsoft.sqlserver.jdbc.SQLServerDriver.connect(SQLServerDriver.java:1168)
        com.mchange.v2.c3p0.DriverManagerDataSource.getConnection(DriverManagerDataSource.java:175)
        com.mchange.v2.c3p0.WrapperConnectionPoolDataSource.getPooledConnection(WrapperConnectionPoolDataSource.java:220)
        com.mchange.v2.c3p0.WrapperConnectionPoolDataSource.getPooledConnection(WrapperConnectionPoolDataSource.java:206)
        com.mchange.v2.c3p0.impl.C3P0PooledConnectionPoolPooledConnectionResourcePoolManager.acquireResource(C3P0PooledConnectionPool.java:203)
        com.mchange.v2.resourcepool.BasicResourcePool.doAcquire(BasicResourcePool.java:1138)
        com.mchange.v2.resourcepool.BasicResourcePool.doAcquireAndDecrementPendingAcquiresWithinLockOnSuccess(BasicResourcePool.java:1125)
        com.mchange.v2.resourcepool.BasicResourcePool.access0(BasicResourcePool.java:44)
        com.mchange.v2.resourcepool.BasicResourcePool$ScatteredAcquireTask.run(BasicResourcePool.java:1870)
        com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread.run(ThreadPoolAsynchronousRunner.java:696)
    Thread[C3P0PooledConnectionPoolManager[identityToken->z8kfsx9l1adv4kd1qtfdi6|659f3099]-HelperThread-#1,5,main]
        sun.nio.ch.EPollArrayWrapper.epollWait(Native Method)
        sun.nio.ch.EPollArrayWrapper.poll(EPollArrayWrapper.java:269)
        sun.nio.ch.EPollSelectorImpl.doSelect(EPollSelectorImpl.java:93)
        sun.nio.ch.SelectorImpl.lockAndDoSelect(SelectorImpl.java:86)
        sun.nio.ch.SelectorImpl.select(SelectorImpl.java:97)
        com.microsoft.sqlserver.jdbc.SocketFinder.findSocketUsingJavaNIO(IOBuffer.java:2438)
        com.microsoft.sqlserver.jdbc.SocketFinder.findSocket(IOBuffer.java:2290)
        com.microsoft.sqlserver.jdbc.TDSChannel.open(IOBuffer.java:551)
        com.microsoft.sqlserver.jdbc.SQLServerConnection.connectHelper(SQLServerConnection.java:1962)
        com.microsoft.sqlserver.jdbc.SQLServerConnection.login(SQLServerConnection.java:1627)
        com.microsoft.sqlserver.jdbc.SQLServerConnection.connectInternal(SQLServerConnection.java:1458)
        com.microsoft.sqlserver.jdbc.SQLServerConnection.connect(SQLServerConnection.java:772)
        com.microsoft.sqlserver.jdbc.SQLServerDriver.connect(SQLServerDriver.java:1168)
        com.mchange.v2.c3p0.DriverManagerDataSource.getConnection(DriverManagerDataSource.java:175)
        com.mchange.v2.c3p0.WrapperConnectionPoolDataSource.getPooledConnection(WrapperConnectionPoolDataSource.java:220)
        com.mchange.v2.c3p0.WrapperConnectionPoolDataSource.getPooledConnection(WrapperConnectionPoolDataSource.java:206)
        com.mchange.v2.c3p0.impl.C3P0PooledConnectionPoolPooledConnectionResourcePoolManager.acquireResource(C3P0PooledConnectionPool.java:203)
        com.mchange.v2.resourcepool.BasicResourcePool.doAcquire(BasicResourcePool.java:1138)
        com.mchange.v2.resourcepool.BasicResourcePool.doAcquireAndDecrementPendingAcquiresWithinLockOnSuccess(BasicResourcePool.java:1125)
        com.mchange.v2.resourcepool.BasicResourcePool.access0(BasicResourcePool.java:44)
        com.mchange.v2.resourcepool.BasicResourcePool$ScatteredAcquireTask.run(BasicResourcePool.java:1870)
        com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread.run(ThreadPoolAsynchronousRunner.java:696)
    Thread[C3P0PooledConnectionPoolManager[identityToken->z8kfsx9l1adv4kd1qtfdi6|659f3099]-HelperThread-#0,5,main]
        sun.nio.ch.EPollArrayWrapper.epollWait(Native Method)
        sun.nio.ch.EPollArrayWrapper.poll(EPollArrayWrapper.java:269)
        sun.nio.ch.EPollSelectorImpl.doSelect(EPollSelectorImpl.java:93)
        sun.nio.ch.SelectorImpl.lockAndDoSelect(SelectorImpl.java:86)
        sun.nio.ch.SelectorImpl.select(SelectorImpl.java:97)
        com.microsoft.sqlserver.jdbc.SocketFinder.findSocketUsingJavaNIO(IOBuffer.java:2438)
        com.microsoft.sqlserver.jdbc.SocketFinder.findSocket(IOBuffer.java:2290)
        com.microsoft.sqlserver.jdbc.TDSChannel.open(IOBuffer.java:551)
        com.microsoft.sqlserver.jdbc.SQLServerConnection.connectHelper(SQLServerConnection.java:1962)
        com.microsoft.sqlserver.jdbc.SQLServerConnection.login(SQLServerConnection.java:1627)
        com.microsoft.sqlserver.jdbc.SQLServerConnection.connectInternal(SQLServerConnection.java:1458)
        com.microsoft.sqlserver.jdbc.SQLServerConnection.connect(SQLServerConnection.java:772)
        com.microsoft.sqlserver.jdbc.SQLServerDriver.connect(SQLServerDriver.java:1168)
        com.mchange.v2.c3p0.DriverManagerDataSource.getConnection(DriverManagerDataSource.java:175)
        com.mchange.v2.c3p0.WrapperConnectionPoolDataSource.getPooledConnection(WrapperConnectionPoolDataSource.java:220)
        com.mchange.v2.c3p0.WrapperConnectionPoolDataSource.getPooledConnection(WrapperConnectionPoolDataSource.java:206)
        com.mchange.v2.c3p0.impl.C3P0PooledConnectionPoolPooledConnectionResourcePoolManager.acquireResource(C3P0PooledConnectionPool.java:203)
        com.mchange.v2.resourcepool.BasicResourcePool.doAcquire(BasicResourcePool.java:1138)
        com.mchange.v2.resourcepool.BasicResourcePool.doAcquireAndDecrementPendingAcquiresWithinLockOnSuccess(BasicResourcePool.java:1125)
        com.mchange.v2.resourcepool.BasicResourcePool.access0(BasicResourcePool.java:44)
        com.mchange.v2.resourcepool.BasicResourcePool$ScatteredAcquireTask.run(BasicResourcePool.java:1870)
        com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread.run(ThreadPoolAsynchronousRunner.java:696)

Subsequently I made some changes following the advice on different websites:

随后我按照不同网站上的建议做了一些更改:

System.setProperty("com.mchange.v2.log.MLog", "com.mchange.v2.log.FallbackMLog");
System.setProperty("com.mchange.v2.log.FallbackMLog.DEFAULT_CUTOFF_LEVEL", "WARNING");

// Create db pool
final ComboPooledDataSource cpds = new ComboPooledDataSource() ;

// Driver
cpds.setDriverClass( "com.microsoft.sqlserver.jdbc.SQLServerDriver" ); // loads the jdbc driver                     

// Url
cpds.setJdbcUrl( "jdbc:xxxx://xxxxx:xxxx;database=xxxxx;" );

// Username / Password
cpds.setUser( "xxxx" ) ;
cpds.setPassword( "xxxx" ) ;                                  

// Start size of db pool
cpds.setInitialPoolSize( 8 );

// Min and max db pool size
cpds.setMinPoolSize(  8 ) ;
cpds.setMaxPoolSize( 10 ) ;

// ????
cpds.setNumHelperThreads( 5 ) ;

// Max allowed time to execute statement for a connection
// @See http://stackoverflow.com/questions/14730379/apparent-deadlock-creating-emergency-threads-for-unassigned-pending-tasks
cpds.setMaxAdministrativeTaskTime( 60 ) ;

// ?????
cpds.setMaxStatements( 180 ) ;
cpds.setMaxStatementsPerConnection( 180 ) ;

// ?????
cpds.setUnreturnedConnectionTimeout( 60 ) ;

// ?????
cpds.setStatementCacheNumDeferredCloseThreads(1);

// We make a test : open and close opened connection
cpds.getConnection().close() ;

After these changes, after the execution of some jobs, the application freezes for several ten of seconds and then displays this error message:

这些更改后,在执行某些作业后,应用程序会冻结数十秒,然后显示此错误消息:

[WARNING] A task has exceeded the maximum allowable task time. Will interrupt() thread [Thread[C3P0PooledConnectionPoolManager[identityToken->z8kfsx9l1ao3z0x88z7oi|4dd889bd]-HelperThread-#4,5,main]], with current task: com.mchange.v2.resourcepool.BasicResourcePoolDestroyResourceTask@4128b402
[WARNING] Thread [Thread[C3P0PooledConnectionPoolManager[identityToken->z8kfsx9l1ao3z0x88z7oi|4dd889bd]-HelperThread-#4,5,main]] interrupted.
[WARNING] A task has exceeded the maximum allowable task time. Will interrupt() thread [Thread[C3P0PooledConnectionPoolManager[identityToken->z8kfsx9l1ao3z0x88z7oi|4dd889bd]-HelperThread-#3,5,main]], with current task: com.mchange.v2.resourcepool.BasicResourcePoolDestroyResourceTask@5d6aab6d
[WARNING] Thread [Thread[C3P0PooledConnectionPoolManager[identityToken->z8kfsx9l1ao3z0x88z7oi|4dd889bd]-HelperThread-#3,5,main]] interrupted.
[WARNING] A task has exceeded the maximum allowable task time. Will interrupt() thread [Thread[C3P0PooledConnectionPoolManager[identityToken->z8kfsx9l1ao3z0x88z7oi|4dd889bd]-HelperThread-#0,5,main]], with current task: com.mchange.v2.resourcepool.BasicResourcePoolDestroyResourceTask@70a3328f
[WARNING] Thread [Thread[C3P0PooledConnectionPoolManager[identityToken->z8kfsx9l1ao3z0x88z7oi|4dd889bd]-HelperThread-#0,5,main]] interrupted.

My questions are :

我的问题是:

  1. Why does the application work perfectly in a development environment and encounters these problems during production?
  2. Above all, how to remedy it?
  3. When a connection reaches the maximum number of statements defined with setMaxStatements and setMaxStatementsPerConnection, what happens to it? The connection is closed then another takes over while another one is created?
  4. I did not quite understand the impact that the setStatementCacheNumDeferredCloseThreads function has on my application.
  1. 为什么应用在开发环境下能完美运行,在生产中却遇到这些问题?
  2. 最重要的是,如何补救?
  3. 当连接达到用 setMaxStatements 和 setMaxStatementsPerConnection 定义的最大语句数时,它会发生什么?连接关闭然后另一个接管,同时创建另一个?
  4. 我不太明白 setStatementCacheNumDeferredCloseThreads 函数对我的应用程序的影响。

Thank you very much ! Have a good day.

非常感谢你 !祝你有美好的一天。

回答by Steve Waldman

OK. So. Your basic problem is simple. In your production environment, Connection acquisition attempts are eventually freezing, that is they are neither succeeding nor failing with an Exception, they are simply hanging. Ultimately, this is what you have to debug: Why is it that when c3p0 tries to connect to your production database, sometimes those calls to Driver.connect()hang? Whatever is causing that is outside of c3p0's control. You could be hitting limits in total connections at the DBMS side (not from this application, your maxPoolSizeis quite modest, but perhaps your production server is overextended). If you are running on an older JVM, there was a known problem with hangs to SQLServer, see e.g. JDBC connection hangs with no response from SQL Server 2008 r2Driver.getConnection hangs using SQLServer driver and Java 1.6.0_29but I doubt you are running Java 6 at this point, and I don't know of more recent issues. In any case, it's quite clear from your logs that this is what is happening: c3p0 is trying to acquire Connections from the DBMS, the DBMS is hanging indefinitely, eventually all of c3p0's helper threads get saturated by hung tasks and you see an APPARENT DEADLOCK. To resolve the issue, you have to debug why attempts by your JDBC driver to connect to your DBMS sometimes hang.

行。所以。你的基本问题很简单。在您的生产环境中,连接获取尝试最终会被冻结,也就是说,它们既不会成功也不会因异常而失败,它们只是挂起。最终,这就是您必须调试的内容:为什么当 c3p0 尝试连接到您的生产数据库时,有时这些调用会Driver.connect()挂起?无论是什么原因,都超出了 c3p0 的控制范围。您可能会在 DBMS 端达到总连接数的限制(不是来自这个应用程序,您maxPoolSize的连接很有限,但可能您的生产服务器过度扩展)。如果您在较旧的 JVM 上运行,则存在 SQLServer 挂起的已知问题,请参阅例如JDBC connection hangs with no response from SQL Server 2008 r2Driver.getConnection 使用 SQLServer 驱动程序和 Java 1.6.0_29 挂起,但我怀疑您此时正在运行 Java 6,而且我不知道最近的问题。在任何情况下,从您的日志中可以清楚地看出正在发生的事情:c3p0 试图从 DBMS 获取连接,DBMS 无限期挂起,最终 c3p0 的所有辅助线程都被挂起的任务饱和,您会看到APPARENT DEADLOCK. 要解决此问题,您必须调试 JDBC 驱动程序连接 DBMS 的尝试有时会挂起的原因。

Most of the things you did after scrounging random troubleshooting posts were not very relevant to this issue. The thing that did cause your logs to change was this setting

您在搜索随机故障排除帖子后所做的大多数事情都与此问题不太相关。确实导致您的日志更改的原因是此设置

cpds.setMaxAdministrativeTaskTime( 60 );

That works around the problem in an ugly way. If a task hangs for a long period of time, that setting causes c3p0 to interrupt()the Thread on which it is running and abandon it. That prevents the deadlocks, but doesn't address their cause.

这以一种丑陋的方式解决了这个问题。如果一个任务长时间挂起,该设置会导致 c3p0 到interrupt()它正在运行的线程并放弃它。这可以防止死锁,但并没有解决死锁的原因。

There is a surprising change, though, between the two logs. The replacement of APPARENT DEADLOCKspew with reports that a 'task has exceeded the maximum allowable task time' were to be expected. But interestingly, in your second log, the tasks that get interrupt()ed are not Connection acquisition attempts, but Connection destruction attempts. I don't know why that has changed, but the core issue is the same: attempts by your JDBC driver to interact with your DBMS are freezing indefinitely, nether succeeding nor failing promptly with an Exception. That is what you need to debug.

但是,两个日志之间存在令人惊讶的变化。APPARENT DEADLOCK用“任务已超过最大允许任务时间”的报告替换spew 是意料之中的。但有趣的是,在你的第二个日志中,得到interrupt()ed的任务不是 Connection 获取尝试,而是 Connection 破坏尝试。我不知道为什么会发生变化,但核心问题是相同的:您的 JDBC 驱动程序尝试与您的 DBMS 交互的尝试无限期地冻结,无论成功还是失败都会立即出现异常。这就是您需要调试的内容。

If you can't resolve the problem, you may be able to work around it. It's very ugly, but if you reduce maxAdministrativeTaskTime(say to 30) and increase numHelperThreads(say to 20), you may be able to largely eliminate the application pauses, as long as the freezes are infrequent. Increasing numHelperThreadsincreases the number of frozen tasks c3p0's Thread pool can tolerate before being completely blocked. reducing maxAdministrativeTaskTimereduces the lifetime of blockages. Obviously, the right thing to do is to debug the problem between the JDBC driver and the DBMS. But if that proves impossible, sometimes a workaround is the best you can do.

如果您无法解决问题,您也许可以解决它。这非常难看,但如果你减少maxAdministrativeTaskTime(说到30)和增加numHelperThreads(说到20),你可能能够在很大程度上消除应用程序暂停,只要冻结不频繁。增加会numHelperThreads增加 c3p0 的线程池在被完全阻塞之前可以容忍的冻结任务的数量。减少maxAdministrativeTaskTime会减少堵塞的寿命。显然,正确的做法是调试JDBC驱动和​​DBMS之间的问题。但是,如果事实证明这是不可能的,有时您可以采取一种解决方法。

I would eliminate (at least for now) these three settings:

我会消除(至少现在)这三个设置:

// ?????
cpds.setMaxStatements( 180 ) ;
cpds.setMaxStatementsPerConnection( 180 ) ;

// ?????
cpds.setStatementCacheNumDeferredCloseThreads(1);

The first two turn Statement caching on, which may or may not be desirable from a performance perspective for your application. But they increase the complexity of c3p0's interaction with the DBMS. SQLServer (among several databases) is very fragile with respect to multithreaded use of a Connection (which, at least per early versions of the JDBC spec, should be legal, but too bad). Setting statementCacheNumDeferredCloseThreadsto 1ensures that the Statement cache doesn't try to close an expiring Statement while the Connection is otherwise in use, and so prevents freezes, APPARENT DEADLOCKs that show up usually as hung Statement close tasks, not your issue. If you turn the Statement cache on, by all means keep statementCacheNumDeferredCloseThreadsset to 1to avoid freezes. But the safest, sanest thing is to avoid all the complexity of the Statement cache until you have your main issue debugged. You can restore these settings later to test whether they improve your application's performance. (If you do turn the Statement cache back on, my suggestion is that you just set maxStatementsPerConnection, and do not set a global maxStatements, or if you set both, set the per-Connection limit to a value much smaller than the global limit. But again, for now, just turn all this stuff off.)

前两个开启 Statement 缓存,从您的应用程序的性能角度来看,这可能是可取的,也可能不是。但是它们增加了 c3p0 与 DBMS 交互的复杂性。SQLServer(在多个数据库中)在连接的多线程使用方面非常脆弱(至少对于 JDBC 规范的早期版本,这应该是合法的,但太糟糕了)。设置statementCacheNumDeferredCloseThreads1可确保 Statement 缓存不会在 Connection 以其他方式使用时尝试关闭到期的 Statement,从而防止冻结,APPARENT DEADLOCK通常显示为挂起的 Statement 关闭任务,而不是您的问题。如果您打开 Statement 缓存,请务必保持statementCacheNumDeferredCloseThreads设置为1以避免冻结。但最安全、最明智的做法是在调试主要问题之前避免语句缓存的所有复杂性。您可以稍后恢复这些设置以测试它们是否提高了应用程序的性能。(如果您确实重新打开 Statement 缓存,我的建议是您只设置maxStatementsPerConnection而不设置 global maxStatements,或者如果您同时设置了两者,请将每个连接限制设置为远小于全局限制的值。但同样,现在,只需关闭所有这些东西。)

To get to your specific questions:

要解决您的具体问题:

  1. Why does the application work perfectly in a development environment and encounters these problems during production?
  1. 为什么应用在开发环境下能完美运行,在生产中却遇到这些问题?

That's an important clue that you want to use in debugging the hang between you JDBC driver and your DBMS. Something about your production server leads to a hang that does not show up in your development server. That may just a matter of the relatively low load on your development server and high load on your production server. But there may be other differences in settings that provide clues about the hangs.

这是您想在调试 JDBC 驱动程序和 DBMS 之间的挂起时使用的重要线索。关于您的生产服务器的某些事情会导致在您的开发服务器中没有出现的挂起。这可能只是您的开发服务器上的负载相对较低而生产服务器上的负载较高的问题。但是设置中可能存在其他差异,可以提供有关挂起的线索。

  1. Above all, how to remedy it?
  1. 最重要的是,如何补救?

Debug the hangs. If you cannot debug the hangs, try working around the issue with a shorter maxAdministrativeTaskTimeand a larger numHelperThreads.

调试挂起。如果您无法调试挂起,请尝试使用更短maxAdministrativeTaskTime和更大的numHelperThreads.

  1. When a connection reaches the maximum number of statements defined with setMaxStatements and setMaxStatementsPerConnection, what happens to it? The connection is closed then another takes over while another one is created?
  1. 当连接达到用 setMaxStatements 和 setMaxStatementsPerConnection 定义的最大语句数时,它会发生什么?连接关闭然后另一个接管,同时创建另一个?

A Connection doesn't reach any of those things. These are parameters that describe the Statement cache. When the total number of cached Statements hits maxStatements, the least-recently-used cached Statement is closed (just the Statement, not its Connection). When a Connection's maxStatementsPerConnectionis hit, that Connection's least-recently-used cached Statement is closed (but the Connection itself remains open and active).

Connection 不会到达任何这些东西。这些是描述语句缓存的参数。当缓存的 Statements 总数达到 时maxStatements,最近最少使用的缓存 Statement 将关闭(只是 Statement,而不是它的 Connection)。当一个连接maxStatementsPerConnection被命中时,该连接的最近最少使用的缓存语句被关闭(但连接本身保持打开和活动状态)。

  1. I did not quite understand the impact that the setStatementCacheNumDeferredCloseThreads function has on my application.
  1. 我不太明白 setStatementCacheNumDeferredCloseThreads 函数对我的应用程序的影响。

If you are using the Statement cache (again, I recommend you turn it off for now), this setting ensures that expired Statements (see above) are not close()ed while their parent Connection is in use by some other Thread. The setting creates a dedicated Thread (or Threads) whose sole purpose is to wait for when Connections are no longer in use and close them only then (thus, statement cache deferred close threads).

如果您正在使用 Statement 缓存(同样,我建议您现在将其关闭),此设置可确保过期的 Statements(见上文)close()在其父 Connection 被其他线程使用时不会被ed。该设置创建一个专用线程(或多个线程),其唯一目的是等待不再使用连接并仅在那时关闭它们(因此,语句缓存延迟关闭线程)。

I hope this helps!

我希望这有帮助!

Update: The bug that you are experiencing does look very much like the Java 6 bug. If you are running Java 6, you are in luck, the fix is probably just to update your production JVM to the most recent version of Java 6.

更新:您遇到的错误看起来很像Java 6 错误。如果您正在运行 Java 6,那么您很幸运,修复可能只是将生产 JVM 更新到 Java 6 的最新版本。