トップ «前の日記(2009-11-05) 最新 次の日記(2009-11-07)» 編集

日々の破片

Subscribe with livedoor Reader
著作一覧

2009-11-06

_ コネクションプール

いつもはだらだらと最大5クライアントくらいからのアクセスがあるとすると、コネクションプールは5つ用意しておけば良いわけだが、ある日、突然アクセスが集中して同時に40クライアントをさばく必要が出る。当然、その時点で40コネクションが作られる。

この40コネクションがプールに残った状態で、またアクセスが平常に戻るとする。賢いコネクションプールであれば、プールされたコネクションを順に回すから40コネクションはまんべんなく利用できる。LIFOというかキューで管理しているような場合だ。ここで、FIFOを利用されるとつまりスタックだが、底から35コネクション分はまったく利用されない。

そして1週間くらい経過したところで、また40とか50とかの嵐が吹く。

1週間何もしなければそのコネクションは無応答非活性(non acitivity)タイムアウトとかしているだろう。しかし、余分なことをしないソケットだとタイムアウトして切断状態になっていてもその時点で利用者は気づけない。リクエストに応じてDBにアクセスして初めて切断状態に気づき、SQLExceptionをスローする。

処理は中途半端に走っているため、そのリクエストは異常終了させるほかなくなる。

ということを想定すれば、コネクションプールの機能として、利用開始時の接続チェックであるとか、長時間アイドル状態にあるコネクションの回収といった処理は必然だ。

が、JDBCにはそういったAPIはない。

commonsにはしょぼいコネクションプールがあり、上記のようなプロパティが提供されている(JNDI用の設定で記述できる)。が、どういうわけかいきなり100コネクションとか作ろうとすると空振りすることがある。どちらにしてもcommonsは嫌いだからソースを読むより自分で作るほうがましなので、すぐに捨てる。

OracleのJDBCドライバは腰が落ち着かなくてそれはそれで厄介なのだが、10gからのoracle.jdbc.pool.DataSourceから取れるOracleConnectionにはこういったプロパティがある。しかし、これまた厄介な代物だ。

というのは、設定したいプロパティはOracleConnection側にあり、DataSource側にはなく、使いたい場合はプロパティセットを送りこむ必要があり、それをJNDIの設定では記述できない。まあ、Oracle依存の初期化プログラムを書けばよいということだ。

しかし、DataSource#getConnectionがコネクションプールだというのも厄介は厄介なのであった。というのは、異常を検出してconnection#closeを呼んでも単にプールへ戻っていくだけで、またgetConnectionを呼ぶと同じものが返ってくる(例外を起こしたConnectionについてはclose呼び出しで物理接続もろとも廃棄すれば良いと思うのだが、と書いて気づいたが100インスタンスくらい作られていたら10回程度試してもわからないのか。本当のところはどうなんだろうか)。そこで、OracleConnection#close(int)を使って物理接続の廃棄を指定することになる。なんで、ConnectionPooledDataSourceを提供しないんだろうか。まあ、こちらはPooledConnectionというこれまた厄介なものが返ってくるのでそれはそれで面倒な話ではあるが、ojdbc14.jarを参照しなくてもコンパイルできるというメリットはある。

結局、DataSource#getConnectionしたら、dualから1をselectするようなSQLを一回発行し、そこで例外が起きたら、引数つきcloseを呼び出し、またgetConnectionするというのを何度も再試行する処理を記述することになる(何度もというのは、最大で生成済みのすべてのインスタンスを潰す必要があるからだ。もちろんDataSourceは確保したままとしたい場合だ)。


2003|06|07|08|09|10|11|12|
2004|01|02|03|04|05|06|07|08|09|10|11|12|
2005|01|02|03|04|05|06|07|08|09|10|11|12|
2006|01|02|03|04|05|06|07|08|09|10|11|12|
2007|01|02|03|04|05|06|07|08|09|10|11|12|
2008|01|02|03|04|05|06|07|08|09|10|11|12|
2009|01|02|03|04|05|06|07|08|09|10|11|12|
2010|01|02|03|04|05|06|07|08|09|10|11|12|
2011|01|02|03|04|05|06|07|08|09|10|11|12|
2012|01|02|03|04|05|06|07|08|09|10|11|12|
2013|01|02|03|04|05|06|07|08|09|10|11|12|
2014|01|02|03|04|05|06|07|08|09|10|11|12|
2015|01|02|03|04|05|06|07|08|09|10|11|12|
2016|01|02|03|04|05|06|07|08|09|10|11|12|
2017|01|02|03|04|05|06|07|08|09|10|11|12|
2018|01|02|03|04|05|06|07|08|09|10|11|12|
2019|01|02|03|04|05|06|07|

ジェズイットを見習え