JBossにおけるコネクションのバリデーション
JBossを起動したままDBセッションを強制切断してみたら、コネクションプールを自動で再接続してくれなかった。
JBossの再起動は運用上やりたくないので色々と調べてみた。
どんな機能か
コネクションプール中のアイドル状態のコネクションに対して、定期的、もしくはアプリケーションスレッドのコネクション取得直前のタイミングで、コネクションの有効性検証(バリデーション)を行うことができる。
アプリケーションスレッドからのリクエストによってアイドルコネクションを貸し出すんだけど、貸し出す直前にコネクションの有効性チェックを行ってくれる便利機能。
無効になってたら、そのコネクションを破棄して再接続を行ってくれる。
コネクションが無効になるケース
- JBossは稼働したまま、DBだけ再起動した場合
- 一定時間そのコネクションを使用しなかった場合
- KILL文でコネクションを切断した場合
設定例
<validation>
<check-valid-connection-sql>SELECT 1</check-valid-connection-sql>
<validate-on-match>true</validate-on-match>
</validation>
check-valid-connection-sql
バリデーションの際に実行するSQLを指定する。
上記の設定例の場合、プールからコネクションを取得する際に「SELECT 1」というSQL文をDBに発行するようになり、コネクションが無効になってた場合に検知できるようになる。
無効の場合はコネクションを破棄して再接続を行うため、アプリケーション側には例外が発生しない。
validate-on-match
アプリケーションのコネクション取得時にバリデーションを実行するか否かを指定する。
デフォルトはfalse.
その他のパラメータ
valid-connection-checker
バリデーションを行うためのクラス名を指定する。
バリデーションを行うには、このパラメータか上述のcheck-valid-connection-sqlのいずれかを指定する。同時に指定した場合、このパラメータが優先される。
background-validation
アプリケーションのコネクション取得時ではなく、バックグラウンドで定期的にバリデーションを実行するか否かを指定する。
デフォルトはfalse.
background-validation-minutes
バックグラウンドのバリデーションを行う時間の間隔を分で指定。
millisでミリ秒にもできる。
use-fast-fail
バリデーションエラーが発生した場合の新たなコネクションの生成方法(他のコネクションをどう扱うか)を制御する。validate-on-matchをtrueにセットした場合に使用するオプション。
本属性でtrueを指定した場合、新たなコネクションを生成する際に他のコネクションはプール中に残存する。例えばデータベースを再起動したときなど、プール内のコネクションが全て使えなくなっている、というときに再接続を早く行える。プール内の他のコネクションはノータッチなので、使えないコネクションはプールに残ったままになる。
falseの場合、プール中のコネクションを全て使えないものと判断し、全て破棄してから再生成する。デフォルトはfalse.
一般的なバリデーション方式
この機能は、データソースの障害検知において有用なので、プロダクション環境ではよく利用されている。アプリケーションの取得時にバリデーションを行ったほうが、DB再起動・待機系DB切り替え・ネットワーク障害が起きた場合、有効なコネクションを取得できる可能性が高くなる。use-fast-failは特に理由がない限り、デフォルト(false)で良い。
パフォーマンスの懸念
バリデーションを行うと、パフォーマンスに影響が及びますが、検証用SQL文(SELECT 1)そのものは素早く実行されるため、パフォーマンス上の全体的な影響は最低限に保たれる。更に、このSQLが実行されるのは、コネクションが成立した場合においてのみ。よって、ずっとコネクションが保たれていれば、何度も何度も検証用SQL文が投げられることはない。超大規模なアプリの場合は、パフォーマンスの影響を評価してから実装したほうがいいかもしれない。
検証用SQL文の種類
DB | 検証用SQL文 |
---|---|
MySQL | select 1 |
SQL Server | select 1 |
Oracle | select 1 from dual |
PostgreSQL | select version(); |