Batch実行時に、コネクションが切れてしまうことが増えた
実際のエラー文とは違いますが、大体こんな感じのエラー文
ERROR apps.HogeMain - hoge.jdbi.hoge.exceptions.UnableToCreateStatementException: java.sql.SQLException: Connection has already been closed. [statement:"select * from hoges]
とはいえ、毎回コネクションが切れるわけではなく、たまーに切れるという程度
原因調査
結論
- DBコネクションを一定の時間使わないと、自動的にクローズする設定になっていた
- その条件に引っかからないように処理を短くして解決
当時の環境(ざっくり)
-
org.apache.tomcat.jdbc.pool
を使って、DBコネクションを貼っていた
一度DBに接続したものの切断されたと仮定
- エラーを見る限り、「コネクションが既にクローズされている」と出ていたので、一度接続したものの切断されたと仮定
- Batch実行時とエラー発生時のコネクション接続数の差異を確認
- コネクションが減っている!
- (気が向いたら、ここに何かエビデンスを貼る)
- 仮定は合ってそう
誰がコネクションをクローズ
- コネクションをクローズするのは、当時使っていた
org.apache.tomcat.jdbc.pool
? -
org.apache.tomcat.jdbc.pool
の設定を見直し- DBへのアクセスが無いと、自動的にDBコネクションのクローズする設定になっていた
- 具体的には以下の通り
-
removeAbandoned
はクローズ漏れを防ぐために自動的にクローズするかしないかの設定 -
removeAbandonedTimeout
はどれぐらいの時間コネクションを使わなかったら、自動的にクローズするかの時間設定
-
Attribute | Description |
---|---|
removeAbandoned | (boolean) Flag to remove abandoned connections if they exceed the removeAbandonedTimeout. If set to true a connection is considered abandoned and eligible for removal if it has been in use longer than the removeAbandonedTimeout Setting this to true can recover db connections from applications that fail to close a connection. See also logAbandoned The default value is false. |
removeAbandonedTimeout | (int) Timeout in seconds before an abandoned(in use) connection can be removed. The default value is 60 (60 seconds). The value should be set to the longest running query your applications might have. |
解決策
-
removeAbandoned
をfalse
にする- クローズ漏れを防げなくなるので、
true
で動いていたシステムをfalse
に変更するのはリスクがあるかも...変更するときは慎重に
- クローズ漏れを防げなくなるので、
-
removeAbandonedTimeout
の時間を長くする- The value should be set to the longest running query your applications might have. と書いてある通り、時間は上手く設定する必要があります。
- 処理時間を短くし、
removeAbandonedTimeout
に引っかからないようにする
のどれか
まとめ
- 今回は、
tomcat.jdbc.pool
の解決策だったが、違う環境下であっても、既にクローズされているというエラー文が出た時は、コネクションの設定を見返すと解決出来るかもしれない