12

MySQLデータベースでC3P0を使用していくつかの単純な読み取り(SELECT)操作を実行しようとすると、割り込み例外(java.lang.InterruptedException)が発生します。並列スレッドの数を100を超えて増やすと、例外が発生します(5、10、20、60、および100で試しました)。私が実行するステートメントは、次のように単純です。

SELECT `Model.id` FROM `Model` LIMIT 100;

私の接続は、次のプロパティを使用して構成された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=***

テストを実行するマシン上の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)

その警告の理由を知りたいのですが、次に、ソフトウェアの堅牢性と安定性に与える可能性のある影響について知りたいと思います。使用後、結果セット、SQLステートメント、および接続を閉じることに注意してください。最後に、テストが終了したら、メソッドを呼び出してプールを閉じますComboPooledDataSource#close()。もっと奇妙なことは(そして同期の問題を明らかにするように思われる)、私が以下を使用してプールに十分な時間を与えるならば...

Thread.sleep(10000); // wait for some time
datasource.close();

ログに警告は表示されません!これはC3P0のスレッドセーフの問題を引き起こすと思いますか、それとも私は間違った方法で何かをしていますか?

アップデート1:

すでに述べたものとは別に、を削除する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)

もう少し光を当てるかもしれません...

アップデート2:

これが私の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

疑問を曖昧にするために、接続の最大数が次のように適切に設定されていることを確認しました。

show global variables where Variable_name='max_connections';
+-----------------+-------+
| Variable_name   | Value |
+-----------------+-------+
| max_connections | 1024  | 
+-----------------+-------+
1 row in set (0.00 sec)
4

3 に答える 3

7

その警告は、ここで2007 行目あたりから来ています。接続を取得しようとしてスタックしたスレッドのようです。

おそらく、mysql サーバーが処理するように構成されているよりも多くの接続を取得するようにプールが設定されているためです。デフォルトのmax_connectionは 100 (または mysql のバージョンによっては 151) であるため、これは理にかなっているようです。

そのため、接続を取得しようとしているスレッドは、接続を取得しようとして sleep()/retry ループに入ります - ただし、プールがそのループ内にある間にプール全体を閉じます - そのスレッドは中断されるため、閉じたときにすべてのリソースを再利用できますプール。

これまでのところ、害はないようです。コードは、完了時に接続をプールに返し、他のユーザーが使用できるようにアイドル状態のままにし、すべてのクエリを通過させる可能性があります。

于 2011-02-21T17:21:03.227 に答える
1

私はちょうどこの問題に遭遇しました。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 ]]

および修正:

[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 ]]

したがって、すべてが正しく設定されているわけではありません。より具体的には、呼び出して null 値を修正するときにsetDriverClasssetJdbcUrlInterruptedException を削除しました

于 2012-06-21T20:03:32.367 に答える
1

おそらく、InterruptedExceptionc3p0 スレッドの一部が接続を待機しており、close()これらのスレッドを呼び出すと中断されるため、正常です。ただし、セットアップ (100 クライアント、1000 サーバー接続) によると、リソースを待機する必要性はそれほど明白ではありません。
あなたが本当に興味を持っているなら、最も信頼できる解決策はc3p0ログを見て、おそらくいくつかのログを追加して再コンパイルすることです...

于 2011-02-16T15:09:47.300 に答える