java C3P0 线程安全吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5017514/
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
Is C3P0 thread-safe?
提问by Pantelis Sopasakis
An interruption exception (java.lang.InterruptedException) occurs as I'm trying to perform some simple read (SELECT) operations using C3P0 on a MySQL database. The exception occurs as I increase the number of parallel threads more than 100 (I have tried with 5,10,20,60 and 100). The statement I execute is as simple as :
当我尝试在 MySQL 数据库上使用 C3P0 执行一些简单的读取 (SELECT) 操作时,发生中断异常 (java.lang.InterruptedException)。当我将并行线程的数量增加到 100 以上时会发生异常(我已经尝试了 5、10、20、60 和 100)。我执行的语句很简单:
SELECT `Model.id` FROM `Model` LIMIT 100;
My connections are pooled from a ComboPooledDataSource which is configured using the following properties (see also the C3P0 manual):
我的连接是从使用以下属性配置的 ComboPooledDataSource 汇集的(另请参阅C3P0 手册):
c3p0.jdbcUrl=jdbc:mysql...
c3p0.debugUnreturnedConnectionStackTraces=true
c3p0.maxIdleTime=5
c3p0.maxPoolSize=1000
c3p0.minPoolSize=5
c3p0.initialPoolSize=5
c3p0.acquireIncrement=3
c3p0.acquireRetryAttempts=50
c3p0.numHelperThreads=20
c3p0.checkoutTimeout=0
c3p0.testConnectionOnCheckin=true
c3p0.testConnectionOnCheckout=true
user=***
password=***
The MySQL server on the machine I run the tests is configured to accept 1024 connections and the unit tests I run are successfully executed (the data are retrieved from the database as expected). However, in the C3P0 log file, I find the following warning:
我运行测试的机器上的 MySQL 服务器配置为接受 1024 个连接,并且我运行的单元测试成功执行(数据按预期从数据库中检索)。但是,在 C3P0 日志文件中,我发现以下警告:
15:36:11,449 WARN BasicResourcePool:1876 - com.mchange.v2.resourcepool.BasicResourcePool@9ba6076 -- Thread unexpectedly interrupted while performing an acquisition attempt.
java.lang.InterruptedException: sleep interrupted
at java.lang.Thread.sleep(Native Method)
at com.mchange.v2.resourcepool.BasicResourcePool$AcquireTask.run(BasicResourcePool.java:1805)
at com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread.run(ThreadPoolAsynchronousRunner.java:547)
I'd like to know the reason for that warning and second its possible impact on the software's robustness and stability. Note that after use, I close the result set, the SQL statement and the connection. Finally, once the test is over, I close the pool by calling the method ComboPooledDataSource#close()
. What is more weird (and seems to be to reveal a synchronization problem), is that if I give enough time to the pool using the following...
我想知道该警告的原因,其次是它对软件健壮性和稳定性的可能影响。请注意,使用后,我关闭了结果集、SQL 语句和连接。最后,一旦测试结束,我通过调用方法关闭池ComboPooledDataSource#close()
。更奇怪的是(似乎揭示了同步问题),如果我使用以下方法为池提供足够的时间......
Thread.sleep(10000); // wait for some time
datasource.close();
No warnings will appear in the logs! Dο you think this raises a thread safety issue for C3P0 or am I doing something the wrong way?
日志中不会出现警告!你认为这会引发 C3P0 的线程安全问题还是我做错了什么?
Update 1:
更新 1:
Let me mention that removing the Thread.sleep(10000)
, apart from what already mention, causes the following info to be logged in the MySQL log file:
让我提一下Thread.sleep(10000)
,除了已经提到的内容之外,删除会导致以下信息记录在 MySQL 日志文件中:
110221 14:57:13 [Warning] Aborted connection 9762 to db: 'myDatabase' user: 'root'
host: 'localhost' (Got an error reading communication packets)
Might shed some more light...
可能会散发出更多的光...
Update 2:
更新 2:
Here is my MySQL server configuration. The number of maximum allowed connections by server is set to 1024 (as I mentioned above) which is adequate for what I'm trying to do.
这是我的 MySQL 服务器配置。服务器允许的最大连接数设置为 1024(如上所述),这足以满足我的尝试。
[mysqld]
max_allowed_packet = 64M
thread_concurrency = 8
thread_cache_size = 8
thread_stack = 192K
query_cache_size = 0
query_cache_type = 0
max_connections = 1024
back_log = 50
innodb_thread_concurrency = 6
innodb_lock_wait_timeout = 120
log_warnings
To obfuscate any doubt, I verified that the maximum number of connections is properly set by:
为了消除任何疑问,我验证了最大连接数是否正确设置:
show global variables where Variable_name='max_connections';
+-----------------+-------+
| Variable_name | Value |
+-----------------+-------+
| max_connections | 1024 |
+-----------------+-------+
1 row in set (0.00 sec)
采纳答案by nos
That warning comes from around line 2007 here. It seems to be a thread stuck trying to aquire a connection.
该警告来自此处的2007 行左右。这似乎是一个试图获得连接的线程。
Perhaps because the pool is set up to aquire more connections than what your mysql server is configured to handle. This seems to make sense, as the default max_connectionis 100 (or 151 depending on your mysql version)
可能是因为该池设置为获取比您的 mysql 服务器配置为处理的连接更多的连接。这似乎是有道理的,因为默认的max_connection是 100(或 151,具体取决于您的 mysql 版本)
So that thread trying to aquire a connection goes in to a sleep()/retry loop trying to aquire the connection - however you close the whole pool while it's inside that loop - that thread gets interrupted so all resources can be reclaimed when you close the pool.
因此,尝试获取连接的线程进入 sleep()/retry 循环以尝试获取连接 - 但是您在该循环内关闭了整个池 - 该线程被中断,因此当您关闭时可以回收所有资源水池。
So far, it seems no harm done, your code likely returns connections to the pool when you're done with it leaving them idle for others to use, and all your queries get through.
到目前为止,似乎没有什么坏处,您的代码可能会在您完成后将连接返回到池中,让它们空闲以供其他人使用,并且您的所有查询都可以通过。
回答by demongolem
I just ran into this problem. Here was my setting for the DataSource:
我刚刚遇到了这个问题。这是我对数据源的设置:
[java:comp/env/jdbc/pooledDS] = [com.mchange.v2.c3p0.ComboPooledDataSource [ acquireIncrement -> 3, acquireRetryAttempts -> 30, acquireRetryDelay -> 1000, autoCommitOnClose -> false, automaticTestTable -> null, breakAfterAcquireFailure -> false, checkoutTimeout -> 0, connectionCustomizerClassName -> null, connectionTesterClassName -> com.mchange.v2.c3p0.impl.DefaultConnectionTester, dataSourceName -> 2siwtu8o4m410i1l4tkxb|187c55c, debugUnreturnedConnectionStackTraces -> false, description -> null, driverClass -> null, factoryClassLocation -> null, forceIgnoreUnresolvedTransactions -> false, identityToken -> 2siwtu8o4m410i1l4tkxb|187c55c, idleConnectionTestPeriod -> 0, initialPoolSize -> 3, jdbcUrl -> null, maxAdministrativeTaskTime -> 0, maxConnectionAge -> 0, maxIdleTime -> 0, maxIdleTimeExcessConnections -> 0, maxPoolSize -> 15, maxStatements -> 0, maxStatementsPerConnection -> 0, minPoolSize -> 3, numHelperThreads -> 3, numThreadsAwaitingCheckoutDefaultUser -> 0, preferredTestQuery -> null, properties -> {}, propertyCycle -> 0, testConnectionOnCheckin -> false, testConnectionOnCheckout -> false, unreturnedConnectionTimeout -> 0, usesTraditionalReflectiveProxies -> false ]]
and fixed:
并修复:
[java:comp/env/jdbc/pooledDS] = [com.mchange.v2.c3p0.ComboPooledDataSource [ acquireIncrement -> 3, acquireRetryAttempts -> 30, acquireRetryDelay -> 1000, autoCommitOnClose -> false, automaticTestTable -> null, breakAfterAcquireFailure -> false, checkoutTimeout -> 0, connectionCustomizerClassName -> null, connectionTesterClassName -> com.mchange.v2.c3p0.impl.DefaultConnectionTester, dataSourceName -> 2siwtu8o4m5kux117kgtx|13e754f, debugUnreturnedConnectionStackTraces -> false, description -> null, driverClass -> oracle.jdbc.driver.OracleDriver, factoryClassLocation -> null, forceIgnoreUnresolvedTransactions -> false, identityToken -> 2siwtu8o4m5kux117kgtx|13e754f, idleConnectionTestPeriod -> 0, initialPoolSize -> 3, jdbcUrl -> jdbc:oracle:thin:@localhost:1521:oracle, maxAdministrativeTaskTime -> 0, maxConnectionAge -> 0, maxIdleTime -> 0, maxIdleTimeExcessConnections -> 0, maxPoolSize -> 15, maxStatements -> 0, maxStatementsPerConnection -> 0, minPoolSize -> 3, numHelperThreads -> 3, numThreadsAwaitingCheckoutDefaultUser -> 0, preferredTestQuery -> null, properties -> {user=******, password=******}, propertyCycle -> 0, testConnectionOnCheckin -> false, testConnectionOnCheckout -> false, unreturnedConnectionTimeout -> 0, usesTraditionalReflectiveProxies -> false ]]
So not everything was set correctly. More concretely, when I called setDriverClass
and setJdbcUrl
to correct the null values, I eliminated the InterruptedException
所以并非所有内容都设置正确。更具体地说,当我调用setDriverClass
并setJdbcUrl
更正空值时,我消除了 InterruptedException
回答by Victor Sorokin
Perhaps, InterruptedException
is normal because some of c3p0 threads are waiting for connection and when you call close()
these threads are interrupted. Though, according to your setup (100 clients, 1000 server connections), such necessity to wait for resource is not that obvious.
If you really interested, most reliable solution would be looking to c3p0 logs, perhaps, adding some more logs and recompiling...
也许,这InterruptedException
是正常的,因为一些 c3p0 线程正在等待连接并且当您调用close()
这些线程时被中断。但是,根据您的设置(100 个客户端,1000 个服务器连接),等待资源的必要性并不那么明显。
如果您真的感兴趣,最可靠的解决方案是查看 c3p0 日志,也许,添加更多日志并重新编译...