[Seasar-user:19040] Re: DBコネクション枯渇時にコネクション取得がブロックされ続ける現象について

Koichi Kobayashi [E-MAIL ADDRESS DELETED]
2009年 12月 18日 (金) 05:00:27 JST


小林 (koichik) です.

Date:    Thu, 17 Dec 2009 17:29:28 +0900
From:    阿部 裕康 <[E-MAIL ADDRESS DELETED]>
To:      [E-MAIL ADDRESS DELETED]
Subject: [Seasar-user:19038] DBコネクション枯渇時にコネクション取得がブロックされ続ける現象について

> 動作を調べたところ、
> コネクションが枯渇している状態で新規コネクションを取得しようとすると、
> S2DBCPのConnectionPoolImpl.checkout()の中でcreateConnection()を経由し
> tomcat.DBCPのPoolingDataSource.getConnection()を呼び出し
> コネクションの空き待ちを行います。
> 
> この状態で、既にトランザクションを開始しているスレッドが
> コネクションを取得しようとすると、checkout()がsynchronizedなため
> ブロックされることになります。

コネクションが枯渇しているなら取得でブロックするのは
問題ないです.

それより,コネクションを取得済みのスレッドが
コネクションをプールに返そうとして,checkin() が
synchronized なのでデッドロック状態になるのでしょう.

スレッド A (コネクション取得)
 ConnectionPool のロックを持っている
 コネクションの空き待ち

スレッド B (コネクション解放)
 コネクションを持っている
 ConnectionPool のロック待ち


対処するには createConnection() を synchronized
ブロックの外で呼び出す必要があるのですが,そうすると
コネクションをプールする本来の使い方で maxPoolSize を
守ることが出来なくなります (maxPoolSize を越えて
コネクションが取得されてしまう).

そのため,この件については以下の方法などで
回避するようにしてください.

・DBCP の maxActive ≧ スレッド数となるようにする

DBCP の maxActive を増やすか,Tomcat の
ワーカスレッド数を減らして,DBCP がブロック
しないようにしてください.

requiresNew を使っている場合には一つのスレッドが
同時に複数のコネクションを確保することになるので
注意してください.

・S2DBCP でプールする

Tomcat 側では DBCP ではなく単に DataSource を
定義するだけにして,コネクションは S2DBCP で
プールする.

・S2DBCP および S2JTA を使用しない

JTA 実装も Tomcat 側で定義する.
JOTM とか Atomikos とか.
いっそ Glassfish/Geronimo/JBossAS を使うとか.


-- 
<component name="koichik">
    <property name="fullName">"Koichi Kobayashi"</property>
    <property name="email">"[E-MAIL ADDRESS DELETED]"</property>
    <property name="blog">"http://d.hatena.ne.jp/koichik"</property>
</component>



Seasar-user メーリングリストの案内