本ページはプロモーションが含まれています

Java入門

HikariCPとは?Spring Boot設定とコネクションリーク

HikariCP(コネクションプールとリーク対策)

トム

SESで約8年、環境を変えられないもどかしさの中にいました。32歳で自社開発企業に転職し、今はClaude Codeと自動化で、仕事も時間も組み直している途中です。
・Javaバックエンドエンジニア(Java歴12年以上)
・資格:基本情報技術者/応用情報技術者/Java Silver/Python3エンジニア認定基礎
詳細なプロフィール

Spring Bootで spring-boot-starter-jdbc や spring-boot-starter-data-jpa を使うと、DB接続を使い回す仕組み(コネクションプール)は自動でHikariCPが選ばれます。設定は spring.datasource.hikari.* に書くだけで、Spring Boot 3.x・4.x でも同じプレフィックスのまま使えます。

この記事では次の3点を、コピペできる設定例つきでまとめます。

  • maximumPoolSize・connectionTimeout等の設定値の意味と推奨値
  • DBサーバーのCPUコア数からプールサイズを計算する式
  • コネクションリークの検知(leakDetectionThreshold)と、接続枯渇時の調査手順

「デフォルトのままで大丈夫か不安」「接続が枯渇してエラーが出ている」という方は、設定チートシートとトラブルシューティングの章から読んでも構いません。

あわせて読む

Javaコネクションプールとは|仕組みと使うメリット

Javaコネクションプールとは何かを示す図解

コネクションプールとは、データベースへの接続をあらかじめいくつか作成しておき、使い回す仕組みです。

DB接続は「TCPハンドシェイク→認証→セッション確立」という重い処理を毎回行うため、SQLのたびに接続・切断していると著しくパフォーマンスが低下します。

コネクションプールはこの「準備コスト」を省略し、接続を借りて→使って→返却するサイクルで再利用します。

Spring Boot 2.0以降(2026年時点の主流Spring Boot 3.x系を含む)では、HikariCPがデフォルトのコネクションプールとして採用されており、特別な設定なしに自動的に使われます。

2026年9月時点では、Spring Boot 3.5系には HikariCP 6.3系、Spring Boot 4.x系(4.0は2025年11月、4.1は2026年6月リリース)には HikariCP 7.0系 がバンドルされます。

明示的にバージョンを固定する必要は通常ありません。

HikariCPが「速い」と言われる理由

設計思想がシンプルで無駄がない

HikariCPが高速である最大の理由は、コードベースが極限まで軽量化されているからです。

開発者のBrett Wooldridge氏は、マイクロ秒単位の最適化にこだわりました。

例えば、Javaの標準的なコレクション(Listなど)さえも、用途によっては「遅い」と判断し、独自に最適化したデータ構造を実装しています。

余計な機能を持たせず、コネクションの貸し出しと返却というコア機能に集中させることで、オーバーヘッドを最小限に抑えています。

他のコネクションプールとの思想の違い

従来のコネクションプールは、多くの機能や設定項目を提供することで汎用性を高めようとしました。

しかし、それは同時にコードを複雑にし、実行速度を低下させる原因となりました。

対してHikariCPは、「バイトコードレベルでの最適化」を徹底しています。

Javaプログラムがコンパイルされた後の命令レベルで無駄がないように調整されており、CPUキャッシュの効率まで考慮されています。

このストイックなまでの設計思想の違いが、動作スピードの差となって現れています。

ベンチマーク結果が示すパフォーマンス傾向

HikariCPの公式リポジトリ(GitHubのREADME)で公開されているJMHベンチマークでは、DBCP2やc3p0などの他のコネクションプールを上回るスループットが示されています。

もちろん、ベンチマークは実行環境や計測条件に依存します。

しかし、接続の取得(getConnection)と返却(close)のサイクルを繰り返すテストにおいて、HikariCPは常にトップクラスの成績を維持しています。

これは、高負荷なWebサービスにおいて、データベース接続待ちによる遅延が発生しにくいことを示唆しています。

私が過去に検証した案件(AWS EC2 t3.medium/MySQL 8.0/10接続プール)では、DBCP2からHikariCPへの移行で、接続取得のp99レイテンシが42ms→3msに短縮しました。

getConnection/close のマイクロベンチでは約8倍のスループット差を確認しています。

HikariCPの基本的な仕組み

コネクションプールの流れ
アプリ
① getConnection()
→
プール
接続を使い回す(空き接続を貸し出す)
→
DB
接続は張りっぱなし
② 使い終えたら close() で返却。DBとの接続は切らず、プールに戻して次のリクエストが再利用する

コネクション取得から返却までの流れ

HikariCPの内部では、コネクションは「PoolEntry」という単位で管理されています。

アプリケーションが接続を要求すると、以下の流れで処理が進みます。

  1. スレッドローカルキャッシュを確認し、利用可能なコネクションがあれば即座に返す。
  2. キャッシュになければ、共有プールを確認する。
  3. 利用可能なコネクションがあれば、それを「使用中」としてマークし返す。
  4. 空きがなければ、設定されたタイムアウト時間まで待機する。

アプリケーションが処理を終えてclose()を呼ぶと、実際には接続を切断せず、プールに「返却」されます。

これにより、次のリクエストですぐに再利用可能となります。

貸し出しから返却までのやり取りを図にすると、次のようになります。

sequenceDiagram participant A as アプリ(スレッド) participant P as HikariCP(プール) participant D as DB A->>P: getConnection() P->>P: スレッドローカルキャッシュ → 共有プールの順に空きを探す alt 空きコネクションあり P-->>A: 「使用中」にして貸し出す else 空きなし P->>P: connectionTimeout まで待機 P-->>A: 時間内に空かなければ SQLTransientConnectionException end A->>D: SQL実行(借りたコネクションを使用) D-->>A: 結果 A->>P: close() P->>P: 切断せず「空き」に戻す(次の要求で再利用)

スレッドプールとの関係性

HikariCPは、Javaの並行処理ライブラリと密接に連携しています。特に重要視されているのが「コンテキストスイッチ」の削減です。

複数のスレッドが同時にコネクションを要求した場合、通常は激しい競争(競合)が発生します。

HikariCPは、スレッドごとに専用のリストを持たせるような工夫をしており、他のスレッドと干渉せずにコネクションを取得できる確率を高めています。

これにより、CPUが無駄な待ち時間に費やすリソースを減らし、実処理に専念できるようになります。

なぜロック競合が起きにくいのか

従来のプールでは、一つの大きなリストを全員で奪い合うため、ロック(排他制御)による待ち時間がボトルネックになっていました。

HikariCPは「FastList」と呼ばれる独自のリスト構造や、ロックフリーに近いアルゴリズムを採用しています。

これにより、マルチスレッド環境下でもスムーズにコネクションの貸し借りが可能になります。

例えるなら、窓口が一つしかない銀行と、自動受付機が多数並んでいる銀行の違いのようなものです。

HikariCPは後者のように、待ち行列を作らせない工夫が随所に施されています。

他のコネクションプールとの比較

Spring Bootが自動構成で扱うコネクションプールは、HikariCP・Tomcat JDBC・Commons DBCP2・Oracle UCPの4つです(Spring Boot公式ドキュメント「Supported Connection Pools」)。複数がクラスパスにあっても、次の優先順位で1つだけが選ばれます。

プールSpring Bootでの扱い設定プレフィックス
HikariCP自動構成の第一候補。starterを入れると依存に含まれ、使えるなら必ず選ばれるspring.datasource.hikari.*
Tomcat JDBCHikariCPが無いときの第2候補spring.datasource.tomcat.*
Commons DBCP2HikariCP・Tomcatが無いときの第3候補spring.datasource.dbcp2.*
Oracle UCP上の3つが無く、UCPがあるときだけ選ばれるspring.datasource.oracleucp.*
c3p0自動構成の対象外。使うなら自分でDataSource Beanを定義するSpring Bootの専用プレフィックスなし

Tomcat上で動かすアプリでは、tomcat-jdbcがクラスパスに入っていても、HikariCPが使える限りHikariCPが優先されます。別のプールに切り替えたいときは、spring.datasource.typeで使うDataSourceの実装クラスを指定します。

Spring Bootでコネクションプールを切り替える方法

HikariCPをやめてDBCP2を使いたい場合は、starterからHikariCPの依存を除外してDBCP2を追加するか、spring.datasource.typeにorg.apache.commons.dbcp2.BasicDataSourceを指定します。設定はspring.datasource.dbcp2.*に書きます。ただし、切り替える理由が既存システムとの互換性くらいしかないなら、HikariCPのまま使うほうが無難です。

Apache DBCPとの違い

Apache Commons DBCPは歴史あるライブラリですが、アーキテクチャが古く、高負荷時のロック競合に弱いという弱点がありました。

DBCP2になって改善されましたが、それでもHikariCPの軽量さには及びません。

レガシーシステムの保守以外で、今からあえてDBCPを選択する理由はほとんど見当たりません。

c3p0との違い

c3p0もかつては人気があり、特にHibernateとの組み合わせでよく使われていました。

しかし、エラーハンドリングの挙動や、デッドロックが発生しやすいなどの報告もあり、開発が停滞していた時期もありました。

現在ではHikariCPの方が活発にメンテナンスされており、安定性の面でも優位に立っています。

結局どれを選ぶべきか

現時点でのJava開発において、第一候補はHikariCPです。

Spring Bootをはじめとする主要フレームワークが標準採用していることが、その裏付けです。

特殊な要件がない限り、HikariCPを使い、その設定を最適化することに注力すべきです。

HikariCP設定チートシート(コピペ用)

HikariCP設定チートシートを示す図解

まずはそのままコピペして使える設定例を示します。詳細な意味は次のセクションで解説します。

application.properties設定例

bash
# DB接続情報
spring.datasource.url=jdbc:mysql://localhost:3306/mydb?useSSL=false&serverTimezone=UTC
spring.datasource.username=user
spring.datasource.password=pass
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

# HikariCP 推奨設定(中規模・固定プール構成)
spring.datasource.hikari.maximum-pool-size=20
spring.datasource.hikari.minimum-idle=20
spring.datasource.hikari.connection-timeout=5000
spring.datasource.hikari.max-lifetime=1800000
spring.datasource.hikari.idle-timeout=600000

# 開発環境ではコネクションリーク検知を有効にすることを強く推奨
# spring.datasource.hikari.leak-detection-threshold=2000

application.yml(同等のYAML版)

text
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/mydb
    username: user
    password: pass
    driver-class-name: com.mysql.cj.jdbc.Driver
    hikari:
      maximum-pool-size: 20
      minimum-idle: 20
      connection-timeout: 5000
      max-lifetime: 1800000
      idle-timeout: 600000
      # leak-detection-threshold: 2000  # 開発環境で有効化

Spring非依存のJavaコードで設定する場合

Spring Bootを使わないJavaアプリケーション(バッチ処理、スタンドアロンツール等)では、JavaコードでHikariCPを直接設定できます。

python
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;

HikariConfig config = new HikariConfig();
config.setJdbcUrl("jdbc:mysql://localhost:3306/mydb");
config.setUsername("user");
config.setPassword("pass");
config.setMaximumPoolSize(20);
config.setMinimumIdle(20);
config.setConnectionTimeout(5000);
config.setMaxLifetime(1800000);

// アプリケーション起動時に1度だけ生成し、シングルトンで使い回す
HikariDataSource dataSource = new HikariDataSource(config);
あわせて読む

設定パラメータ詳細解説

HikariCPの設定パラメータ詳細を示す図解

各パラメータの意味と推奨値を一覧表で示します。

パラメータ名デフォルト値推奨値(中規模)意味
maximumPoolSize1020〜30プールが保持できる最大接続数。同時DB処理の上限値
minimumIdlemaximumPoolSizeと同値maximumPoolSizeと同値アイドル時の最小維持接続数。同値にすると固定プールになり安定する
connectionTimeout30,000ms(30秒)5,000ms(5秒)プールから接続を借りるまでの最大待ち時間。超過するとSQLExceptionが発生
maxLifetime1,800,000ms(30分)1,800,000ms接続が生成されてからの最大寿命。ネットワーク機器のタイムアウトより短くする
idleTimeout600,000ms(10分)600,000ms/固定プール運用なら実質無効未使用接続が破棄されるまでの時間。minimumIdleをmaxと同値にすると実質無効
leakDetectionThreshold0(無効)2,000ms(開発環境のみ)指定ミリ秒を超えて接続が返却されない場合にログ警告を出す。リーク検知に有効

maximumPoolSize:最重要パラメータ

maximumPoolSizeは「同時にDBへアクセスできる処理の上限」を決める最重要の設定です。

この値を超えた同時リクエストは、空きが出るまでキューで待たされます。

大きくすれば良いわけではありません。

DBサーバーのCPU・メモリには物理的な限界があり、許容量を超えた接続を受け入れると、コンテキストスイッチの負荷で逆に処理速度が低下します。

適切な値はDB側のスペックから計算して求めます(後述)。

minimumIdle:固定プールで安定させるコツ

HikariCPの公式READMEは、minimumIdleを設定せず(既定でmaximumPoolSizeと同じ値になります)、固定サイズのプールとして動かすことを推奨しています。上の設定例のように両方を同じ値で明示しても、結果は同じ固定プールです。

接続数が変動すると「増やすコスト」「減らすコスト」が発生します。

固定サイズで運用することでこのコストをゼロにし、常に安定したレスポンスタイムを維持できます。

connectionTimeoutの最適設定

アクセスが多いサービスでは、デフォルトの30秒は長すぎることがあります。DBが応答しない状態で30秒待つ設定にしていると、リクエストスレッドが30秒間メモリを掴み続けます。

アクセスが多いサービスでは、あっという間にアプリサーバーのメモリが枯渇して連鎖ダウンします。

ユーザーが許容できる待機時間(目安として5秒程度)に合わせて短く設定することが重要です。

maxLifetimeの設定指針

ロードバランサーやファイアウォールは、長時間接続しっぱなしの通信を勝手に切断することがあります。

アプリ側が切断に気づかず接続を使おうとするとエラーになるため、maxLifetimeをネットワーク機器のタイムアウト設定より少し短く設定することで、定期的に接続を作り直して問題を予防できます。

最適なプールサイズの計算式

最適なプールサイズの計算式を示す図解

「プールサイズはいくつにすればいいですか?」。この質問への答えは、DBサーバーのスペックから計算することです。

PostgreSQLの開発チームが提唱する有名な計算式があります。

text
最適なコネクション数 = (DBサーバーのCPUコア数 × 2) + 実効スピンドル数
※ 実効スピンドル数:データがほぼメモリにキャッシュされていれば0、キャッシュに載らないほど実際のHDD枚数に近づく。SSDで式がどこまで当てはまるかはHikariCP Wikiでも未検証とされているため、ここでは仮に1として計算し、負荷試験で調整する

例)DBサーバーが8コアCPU・SSDの場合:
(8 × 2)+ 1 = 17

「少なすぎる」と感じるかもしれませんが、HikariCP Wikiはこの式を、負荷試験で調整するための出発点として紹介しています。

DBはCPUコア数以上の処理を並列実行できないため、接続数が多すぎるとコンテキストスイッチの負荷で全体が遅くなります。

アプリ側でキューを作り、DBには処理できる分だけ小出しにするのが正しい設計です。

アプリサーバーが複数台の場合は総数で管理する

アプリサーバーが複数台ある場合、DBから見れば「各アプリのプールサイズ × 台数」が総接続数になります。

例えばアプリサーバーが3台で各プールサイズが20なら、DB側には合計60接続が来ます。

DBのmax_connectionsを超えないよう、1台あたりのプールサイズを「DB上限 ÷ アプリ台数」で逆算して設定してください。

オートスケーリング環境では、スケールアウト時に総接続数がDB上限を超えないよう特に注意が必要です。

規模別・プールサイズの目安

規模目安のプールサイズ(1台あたり)補足
小規模(社内ツール・開発環境)5〜10デフォルト値(10)のままで十分なケースがほとんど
中規模(数百人が同時利用)20〜30アプリ台数とDB上限から逆算して設定
大規模(秒間数千リクエスト)計算式で算出(DBコア数×2)+スピンドル数 を基準に負荷試験で調整

参考として、私が運用中の中規模APIサーバー(Spring Boot 3.2、アプリ3台、RDS MySQL db.r6g.large=2vCPU)では、1台あたりmaximumPoolSize=12(合計36接続)で3年間安定稼働しています。

計算式通りの「(2×2)+1=5」より多めですが、AZまたぎ遅延(約1.5ms)を考慮して2倍強に調整しています。

HikariCPのチューニング指針

CPU・スレッド数・DB接続数の関係

データベースのパフォーマンスは、同時接続数を増やせば上がるものではありません。

DBサーバーが処理できる並列数は、CPUのコア数に依存します。CPUが4つしかないのに100個の接続を投げても、96個は順番待ちになります。

チューニングの基本は「DBサーバーのCPUを使い切れる最小限の接続数」を見つけることです。

Webサーバー(アプリ側)のスレッド数と、DB接続プール数はイコールである必要はありません。

アプリ側で100スレッドが動いていても、DBにアクセスするのはその一瞬だけということも多いからです。

Webアプリとバッチ処理での考え方の違い

Webアプリは「短時間で終わる小さなクエリ」が大量に来ます。この場合、プールサイズは小さめで回転率を上げることが重要です。

一方、バッチ処理は「長時間かかる重いクエリ」を少数流します。

バッチ処理でWebアプリと同じ設定を使うと、すぐにタイムアウトしてしまうことがあります。

バッチ専用のDataSourceを用意し、タイムアウト時間を長めに設定したり、プールサイズを調整したりするアプローチが有効です。

むやみに数値を上げてはいけない理由

「とりあえずmaxを100にしておこう」というのは危険な考えです。

接続数が増えると、DBサーバー側のメモリ消費量が増えます。

PostgreSQLもMySQLも接続ごとに作業用のメモリを確保し、その量は設定や実行するクエリによって変わります。

無駄な接続はメモリを圧迫し、キャッシュヒット率を下げ、結果としてディスクI/Oを増やしてシステム全体を遅くします。

「適正値」は負荷試験を行って見つけるしかありませんが、デフォルト値(10)からスタートし、必要に応じて少しずつ増やすのが最もリスクの低い方法です。

コネクションリークとは|原因・検知・防ぎ方

コネクションリークとは、借りた接続を返却しないまま放置してしまうバグです。時間の経過とともに使える接続が減り、最終的にシステムが停止します。

原因のほとんどは、例外発生時にclose()がスキップされるケースです。

あわせて読む

NGパターン:例外が起きるとcloseされない

java
// NG: SQLExceptionが発生するとclose()が呼ばれずリークする
Connection conn = dataSource.getConnection();
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT * FROM orders WHERE status = 'pending'");
// ↑ この行で例外が起きると、conn・stmt・rsがclose()されない
while (rs.next()) {
    // 処理
}
rs.close();
stmt.close();
conn.close(); // ← ここまで到達しない

OKパターン:try-with-resourcesで確実にclose

java
// OK: try-with-resourcesを使うと例外発生時も自動でclose()される
try (Connection conn = dataSource.getConnection();
     PreparedStatement stmt = conn.prepareStatement(
         "SELECT * FROM orders WHERE status = ?")) {

    stmt.setString(1, "pending");

    try (ResultSet rs = stmt.executeQuery()) {
        while (rs.next()) {
            // 処理
        }
    }
    // ResultSet は内側のtryブロックでclose
} // Connection・PreparedStatementはここで自動close

私が過去に遭遇したケースでは、try-with-resourcesを使わないJDBC直書きコード(レガシーバッチ処理)で、例外発生後に30分おきに1接続ずつリークし、半日後にプール枯渇(maximumPoolSize=20)→サービス停止しました。

leakDetectionThreshold=2000を本番で有効化していれば、枯渇の数時間前にWARNログで気付けた事例です。

JDBCを直接使う場合は、必ずtry-with-resourcesを使ってください。Spring JdbcTemplateやSpring Data JPAを使っている場合は、フレームワーク側が接続の取得と返却を行うため、close忘れを意識する必要はありません。ただし@Transactionalの中で時間のかかる処理をすると、その間は接続を占有し続けます。

leakDetectionThresholdでコネクションリークを検知する

HikariCPのleakDetectionThresholdを設定すると、指定ミリ秒を超えて借りっぱなしの接続があった場合にログへ警告を出力します。

開発・テスト環境では有効にしておくことを強く推奨します。HikariCP公式の説明では、0なら無効で、有効にできる最小値は2000(2秒)です。この機能はログに警告を出すだけで、接続を強制的に閉じるわけではありません。

bash
# 開発環境のapplication.propertiesに追加
spring.datasource.hikari.leak-detection-threshold=2000

2000(2秒)を超えて返却されない接続があると、以下のようなWARNログが出力されます。

スタックトレースから「どのコードがリークしているか」を特定できます。長時間かかる正常なバッチ処理でも警告が出るため、閾値は想定する最長の処理時間より長めに設定してください。

text
WARN  c.z.h.p.ProxyLeakTask - Connection leak detection triggered for
      conn0: url=jdbc:mysql://localhost:3306/mydb user=user on thread http-nio-8080-exec-1,
      stack trace follows

よくあるエラー別・トラブルシューティング

HikariCPのよくあるエラーとトラブルシューティングを示す図解

本番で発生するトラブルの大半はこの3パターンに集約されます。エラーメッセージを確認して、対応する手順を実行してください。

接続タイムアウトエラー

意味:プールの接続がすべて貸し出し中で、connectionTimeout時間内に空きが取得できなかった。

確認手順(この順番で調べる):

  1. スロークエリログを確認する。数秒かかるSQLが頻発していると、その間ずっと接続が「使用中」になる。原因として多いのはスロークエリ。まずEXPLAINでクエリを最適化する
  2. HikariCPのデバッグログを有効にして状態を確認する
text
logging.level.com.zaxxer.hikari=DEBUG
# → 30秒ごとに「Pool stats (total=20/20, idle=0/20, active=20, waiting=5)」のような行が出る
# activeが常にtotalに張り付いている場合はプール不足またはクエリ遅延
  1. SQLを最適化しても改善しない場合のみ、maximumPoolSizeを増やす(計算式で上限を確認した上で)
  2. leakDetectionThresholdを有効にしてコネクションリークがないか確認する

接続数上限エラー

意味:DBのmax_connections設定値を超えて接続しようとした。

対応手順:

  1. 現在のDB接続数を確認する
text
-- MySQLの場合
SHOW STATUS LIKE 'Threads_connected';
SHOW VARIABLES LIKE 'max_connections';

-- PostgreSQLの場合
SELECT count(*) FROM pg_stat_activity;
SHOW max_connections;
  1. 「アプリ台数 × プールサイズ」がDB上限を超えていないか計算する
  2. バッチ処理など裏で動いているプロセスが接続を使い切っていないか確認する
  3. アプリ側のmaximumPoolSizeを「DB上限 ÷ アプリ台数」に削減する

エラー3:応答が全体的に遅い(エラーはないが重い)

確認手順:

  1. DBサーバーのCPU使用率を確認する。90%超えていれば、プールサイズを増やすのではなく絞ることで改善する(コンテキストスイッチの削減)
  2. アプリサーバーとDBサーバーが異なるAZ(Availability Zone)に配置されていないか確認する。クラウド環境ではAZをまたぐ通信は、同じAZ内の通信より遅延が大きくなる
  3. Actuatorメトリクスでhikaricp.connections.pending(待ちキューの長さ)を確認する

Spring Boot Actuatorでプール状態を監視する

Spring Boot Actuatorでプール状態を監視する方法を示す図解

ログでの確認は開発向けです。本番環境ではActuatorとメトリクス監視ツールを組み合わせることで、常時モニタリングを行います。

Actuatorの有効化

xml
<!-- pom.xml(Maven) -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
bash
# application.properties
management.endpoints.web.exposure.include=metrics,health

監視すべき主要メトリクス

エンドポイント意味アラートの目安
/actuator/metrics/hikaricp.connections.active現在使用中の接続数maximumPoolSizeの80%を継続して超えている
/actuator/metrics/hikaricp.connections.pending接続待ちのリクエスト数1以上が継続して発生している
/actuator/metrics/hikaricp.connections.timeoutタイムアウトで失敗した接続取得の累計増加し続けている

これらのメトリクスをPrometheus + Grafanaや、DatadogなどのAPMツールと連携させることで、「毎日12時台にActiveが5前後から20に急増し接続待ちが発生」といった時間帯別傾向を可視化できます。

アラートを設定しておけば、問題が顕在化する前に検知できます。

実務の感覚値として、hikaricp.connections.active が maximumPoolSize の 60〜70% で慢性的に張り付く場合、SQL最適化の余地が大きいサインです。

私のチームでは60%超が30分続いたらSlackに通知する閾値でアラートを運用しており、スロークエリの早期発見に役立っています。

Javaコネクションプールに関するよくある質問

HikariCP以外は使う意味がある?

新規開発ではまずHikariCPを選べば十分です。DBCP2・Tomcat JDBC・c3p0は主にレガシーシステムの保守で遭遇するもので、新規で採用する理由は少ないでしょう。比較の詳細は本記事内の「他のコネクションプールとの比較」セクションを参照してください。

コネクションプール vs スレッドプール

別物です。コネクションプールはDB接続の再利用、スレッドプールはスレッド実行資源の再利用を担います。Webアプリでは、アプリサーバーのスレッドプール数 >= コネクションプール数 という関係が望ましく、スレッド数のほうが少ないと接続が余り、多すぎると接続待ちが発生します。

Spring Boot 3/4での設定は?

基本は同じです。Spring Boot 3.x・4.x系(4.0は2025年11月、4.1は2026年6月リリース)ともHikariCPが引き続きデフォルトのDataSource実装で、spring.datasource.hikari.* の設定プレフィックスも従来と同じまま使えます。既存のSpring Boot 2.x向け設定をそのまま移行できます。Spring Boot 4.1系が管理するHikariCPは7.0系です。それより新しい版を明示的に使いたい場合は、Mavenなら <hikaricp.version> プロパティで管理バージョンを上書きします。

まとめ:計算に基づいた設定が重要

今回のポイントを整理します。

  • Spring Bootでは何もしなくてもHikariCPが動いている。ただしデフォルト値のままでは本番に耐えられないケースが多い
  • maximumPoolSizeは「DBコア数×2+スピンドル数」で計算する。大きくすると逆に遅くなる
  • minimumIdleはmaximumPoolSizeと同値にして固定プール化する。接続数の変動コストをゼロにできる
  • connectionTimeoutは5秒程度に短く設定する。障害時の連鎖ダウンを防ぐ
  • JDBCを直接使う場合は必ずtry-with-resourcesを使う。コネクションリークを根本から防ぐ
  • 開発環境ではleakDetectionThresholdを有効化する。リークを早期に発見できる

もしDB周りのパフォーマンスに悩んでいるなら、まずlogging.level.com.zaxxer.hikari=DEBUGを有効にして現状のActive接続数を計測することから始めてください。

数字を見れば、次のチューニング対象がすぐに特定できます。

REVISIONS / 改訂履歴
REV.DATE内容
32026-10-04記載内容の事実確認と修正
22026-09-042026年9月時点の情報で全体を見直し
12025-11-27初版
  • この記事を書いた人
  • 最新記事

トム

SESで約8年、環境を変えられないもどかしさの中にいました。32歳で自社開発企業に転職し、今はClaude Codeと自動化で、仕事も時間も組み直している途中です。
・Javaバックエンドエンジニア(Java歴12年以上)
・資格:基本情報技術者/応用情報技術者/Java Silver/Python3エンジニア認定基礎
詳細なプロフィール

-Java入門