JavaのHikariCPでConnectionの状態を確認する方法
はじめに
HikariCP の Connection Pool を使用してDBアクセスをする際に、取得した Connection が有効かどうかを確認する方法について調査しました。
HikariCPのデフォルト動作
HikariCP は特別な設定をしなくても、コネクションの有効性を自動でチェックする仕組みがあります。
HikariCP では、以下のタイミングで Connection の有効性チェックが行われます。
- Connection をプールから取得するとき
dataSource.getConnection() を呼び出す際、HikariCP は無効な Connection をプールから除外し、常に有効な Connection を返します。
この際、connectionTestQuery が設定されていなければ、HikariCP は isValid() を自動で使用します。 - Connection がアイドル状態のとき
HikariCP は idleTimeout や keepaliveTime の設定に基づいて、アイドル状態の Connection を定期的にチェックし、無効なものをプールから削除します。
設定 | 挙動 |
---|---|
connectionTestQuery を設定しない | JDBC4.0以降なら isValid() を自動で実行してチェック |
connectionTestQuery を設定する | SELECT 1 などの指定されたクエリを実行してチェック |
JDBC4.0以降を使用している場合は、特に何も設定しなくても isValid() による有効性チェックが適用されます。
Connection の有効性を判定する
前述した通り、HikariCP はデフォルトで isValid() を使用した有効性チェックが行われる為、通常は Connection を取得した後で有効性を確認する必要はありませんが、バッチ処理や長時間動作するトランザクションでは、途中でDB接続が切れる可能性があるため、定期的に Connection をチェックしたいケースがあります。
又、クエリを実行中にエラーが発生してリカバリーする際にも、Connection のチェックが有効な場合があります。
Connection の有効性をチェックするには、isValid(int timeout) メソッドを使用します。
import java.sql.Connection;
import java.sql.SQLException;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
public class TestMain {
public static void main(String[] args) {
// HikariCPの設定
HikariConfig config = new HikariConfig();
config.setJdbcUrl("jdbc:mysql://localhost:3306/mydb");
config.setUsername("username");
config.setPassword("password");
// データソースを作成
HikariDataSource dataSource = new HikariDataSource(config);
// コネクションを取得
try (Connection conn = dataSource.getConnection()) {
if (conn.isValid(2)) { // 2秒以内に応答があるかチェック
System.out.println("Connection is valid.");
} else {
System.out.println("Connection is invalid.");
}
} catch (SQLException e) {
e.printStackTrace();
}
// データソースのクローズ
dataSource.close();
}
}
isClosed() では判定できない
isClosed() メソッドでは、Connection がクローズされているかどうかを判定できますが、実際に接続できるかどうかは保証されません。(ネットワークの切断やサーバダウンなどは判定できません)
DBと接続が切れていても、HikariCP がその Connection を認識している場合、false が返る場合があります。
DB接続が有効かどうかを判定するには、isValid() メソッドを使用します。
if (conn.isClosed()) {
System.out.println("Connection is closed.");
} else {
System.out.println("Connection is open.");
}
まとめ
HikariCP は、デフォルトで isValid() を使用して Connection の有効性をチェックしているため、通常は connection.isValid() を手動で呼ぶ必要はありませんが、バッチ処理やリカバリーなどを行う場面では、手動で isValid() を使うことが有用な場合があります。
Discussion