com.mysql.cj.jdbc.exceptions.CommunicationsException: Communications link failure は、MySQL Connector/J(MySQL の JDBC ドライバ)が、MySQL サーバーとの通信そのものに失敗したときに出るエラーです。 SQL の間違いやパスワードの間違いではなく、ネットワークか接続の状態に原因があります。

原因は大きく2つに分かれ、メッセージの2行目を見ればどちらかが分かります。

2行目のメッセージ 状態 主な原因
The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server. 一度もつながっていない MySQL が起動していない、ホスト名・ポートの間違い、bind-address、Docker の localhost、ファイアウォール
The last packet successfully received from the server was 28,800,123 milliseconds ago. The last packet sent successfully to the server was ... つながっていたが途中で切れた wait_timeout による切断、接続プールの設定、ネットワーク機器のタイムアウト、MySQL の再起動
The client was disconnected by the server because of inactivity. 使っていない間にサーバーが切った(MySQL 8.0.24 以降) wait_timeout・interactive_timeout

この記事では、それぞれの原因を実際に起こし、出たメッセージと直し方を並べました。

確認環境:Ubuntu 24.04、MySQL 8.0.46、OpenJDK 21.0.10、Docker 29.4.3(確認日 2026年10月10日)。Connector/J のメッセージは、Connector/J 9.7.0 のソース(メッセージの定義とメッセージを組み立てる処理)で確認しました。下層のネットワークのエラーは、Java の Socket で同じ接続を試して再現しています。

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「Communications link failureの原因と直し方|MySQL」

メッセージの読み方

com.mysql.cj.jdbc.exceptions.CommunicationsException: Communications link failure

The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.
    at com.mysql.cj.jdbc.exceptions.SQLError.createCommunicationsException(...)
    ...
Caused by: com.mysql.cj.exceptions.CJCommunicationsException: Communications link failure
    ...
Caused by: java.net.ConnectException: Connection refused
部分 見るところ
2行目 「has not received any packets」なら一度もつながっていない。「successfully received ... milliseconds ago」ならつながった後に切れた
ミリ秒の数字 つながった後に切れた場合、最後に通信してからの時間。wait_timeout(既定 28800 秒=8時間)を超えていれば、サーバーが切った
一番下の Caused by: 本当の原因。ConnectException・SocketTimeoutException・UnknownHostException・SSLHandshakeException など

Connector/J は、最後に通信した時刻とサーバーの wait_timeout を比べてメッセージを作ります。最後の通信から wait_timeout 以上たっていれば、2行目に続けて is longer than the server configured value of 'wait_timeout' という説明と、接続の有効性を使う前に確かめる・タイムアウトを延ばすといった対処の案が付きます。

一番下の Caused by で原因を分ける

同じ接続を Java の Socket で試すと、Caused by: に出る例外を再現できます。次のプログラムは、DB のホストとポートに TCP でつながるかだけを調べます(ドライバが無くても動くので、切り分けに便利です)。

import java.net.*;

/** DB のホスト・ポートに TCP でつながるかだけを調べる: java Probe.java ホスト ポート */
public class Probe {
    public static void main(String[] a) throws Exception {
        String host = a[0];
        int port = Integer.parseInt(a[1]);
        long t = System.currentTimeMillis();
        try (Socket s = new Socket()) {
            s.connect(new InetSocketAddress(host, port), 5000);   // 5秒でタイムアウト
            System.out.println("OK: " + s.getRemoteSocketAddress());
        } catch (Exception e) {
            System.out.println(e + "  (" + (System.currentTimeMillis() - t) + " ms)");
        }
    }
}
$ java Probe.java localhost 3306
OK: localhost/127.0.0.1:3306
$ java Probe.java localhost 3307
java.net.ConnectException: Connection refused  (7 ms)
$ java Probe.java 10.255.255.1 3306
java.net.SocketTimeoutException: Connect timed out  (5008 ms)
$ java Probe.java db 3306
java.net.UnknownHostException: db  (9 ms)
Caused by: 意味 確認すること
ConnectException: Connection refused 相手のマシンには届いたが、そのポートで待ち受けていない MySQL が起動しているか、ポート番号、bind-address(例2)、Docker の localhost(例3)
SocketTimeoutException: Connect timed out 相手から何も返ってこない IP アドレス、ファイアウォール・セキュリティグループ、VPN
UnknownHostException: db ホスト名を IP アドレスに変換できない ホスト名の綴り、Docker のサービス名とネットワーク(例3)
SSLHandshakeException: No appropriate protocol TLS のバージョンが合わない 例5
EOFException: Can not read response from server つながっていた接続が相手側から切られた 例4

Connection refused はすぐに返り、Connect timed out はタイムアウトの時間(上の例は5秒)だけ待たされます。画面が固まってから出るなら経路、すぐ出るならポートと見当を付けられます。

例1:MySQL が起動していない・ポートが違う

Caused by: java.net.ConnectException: Connection refused
確認 Linux Windows
MySQL が動いているか systemctl status mysql(または mysqld) サービス一覧で「MySQL80」など
待ち受けているポート ss -ltn | grep 3306 netstat -ano | findstr 3306
接続URLのポート jdbc:mysql://ホスト:3306/DB名 同じ

ポートを変えている(3307 など)ことに気づかず、接続URLは 3306 のまま、というケースも多くあります。

例2:bind-address が 127.0.0.1 で、他のマシンからつながらない

MySQL の設定 bind-address が 127.0.0.1 だと、同じマシンの中からしか接続できません。Ubuntu の apt で入れた MySQL は、この設定になっています。

mysql> SHOW VARIABLES LIKE 'bind_address';
+---------------+-----------+
| bind_address  | 127.0.0.1 |
+---------------+-----------+

$ ss -ltn | grep 3306
LISTEN 0      151        127.0.0.1:3306       0.0.0.0:*

この状態で、Docker のコンテナ(別のマシンと同じ扱いになる)からホストの MySQL に接続すると、Connection refused になりました。

== コンテナ → 172.17.0.1:3306(ホストの MySQL)
java.net.ConnectException: Connection refused  (23 ms)

直し方:MySQL の設定ファイル(Ubuntu は /etc/mysql/mysql.conf.d/mysqld.cnf)を変え、MySQL を再起動します。

[mysqld]
bind-address = 0.0.0.0        # すべてのネットワークで待ち受ける(特定のIPだけにもできる)
$ ss -ltn | grep 3306
LISTEN 0      151          0.0.0.0:3306       0.0.0.0:*
== コンテナ → 172.17.0.1:3306
OK: /172.17.0.1:3306

待ち受けを広げたら、ファイアウォールで接続元を絞ることと、MySQL のユーザーを 'app'@'192.168.10.%' のように接続元のホストを指定して作ることを合わせて行います。ユーザーのホストが合わないと、今度は Host '...' is not allowed to connect to this MySQL server(ERROR 1130)になります。

例3:Docker で localhost に接続している

アプリを Docker のコンテナで動かすと、コンテナの中の localhost はコンテナ自身を指します。コンテナから localhost:3306 に接続すると、ホストの MySQL が動いていても Connection refused になりました。

== コンテナ → localhost:3306
java.net.ConnectException: Connection refused  (28 ms)
MySQL の場所 接続URLのホスト
同じ docker compose の別サービス サービス名(jdbc:mysql://db:3306/app)
ホストのマシン(Docker Desktop) host.docker.internal
ホストのマシン(Linux の Docker) host.docker.internal(compose で extra_hosts: ["host.docker.internal:host-gateway"] を付ける)、または docker0 の IP
別のサーバー・クラウドの DB そのホスト名・IP

docker compose では、アプリが MySQL の準備完了より先に起動して、このエラーになることもあります。depends_on だけでは、コンテナが起動するまでしか待ちません。ヘルスチェックを付けて、準備ができるまで待たせます。

services:
  db:
    image: mysql:8.4
    environment:
      MYSQL_ROOT_PASSWORD: example
      MYSQL_DATABASE: app
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-uroot", "-pexample"]
      interval: 5s
      retries: 20
  app:
    build: .
    environment:
      SPRING_DATASOURCE_URL: jdbc:mysql://db:3306/app
    depends_on:
      db:
        condition: service_healthy

例4:つながっていた接続が wait_timeout で切られた

MySQL は、何も通信しない接続を wait_timeout(既定 28800 秒=8時間) で切ります。夜間に使われなかった接続を、朝いちばんに使うと出る、というのが典型です。

wait_timeout を5秒にして、7秒待ってから SQL を送りました。

mysql> SET SESSION wait_timeout = 5;
mysql> SELECT 'before' AS t;
+--------+
| before |
+--------+
(7秒待つ)
mysql> SELECT 'after' AS t;
ERROR 4031 (HY000): The client was disconnected by the server because of inactivity. See wait_timeout and interactive_timeout for configuring this behavior.

MySQL 8.0.24 以降のサーバーは、切る前にこのエラー(4031)を送ります。Connector/J 9.7.0 のソースでは、このエラーを受け取ると CommunicationsException として投げる作りになっているため、Java ではメッセージに The client was disconnected by the server because of inactivity が入ります。それより前のサーバーでは、The last packet successfully received from the server was 28,800,xxx milliseconds ago の形になります。

直し方:wait_timeout を延ばすのではなく、接続プール側で、サーバーに切られる前に接続を入れ替えるようにします。Spring Boot の既定の接続プールは HikariCP です。

# application.yml(Spring Boot + HikariCP)
spring:
  datasource:
    url: jdbc:mysql://db:3306/app
    hikari:
      max-lifetime: 1740000      # 29分。DB やネットワーク機器の切断時間より数秒以上短く
      keepalive-time: 120000     # 2分ごとに使っていない接続を確認する
      connection-timeout: 30000  # プールから接続を借りるまで待つ時間
HikariCP の設定 既定値 決め方
maxLifetime 30分 wait_timeout、ロードバランサー・ファイアウォールの無通信タイムアウトのうち一番短いものより、数秒以上短く
keepaliveTime 2分 無通信で切るネットワーク機器があるなら、その時間より短く
connectionTimeout 30秒 プールが空のときに待つ時間

クラウドの DB では、ロードバランサーや NAT ゲートウェイの無通信タイムアウトが wait_timeout より短いことがあります。この場合、MySQL の設定を延ばしても直りません。maxLifetime をその時間より短くします。

接続URLの autoReconnect=true は、Connector/J の説明でも「推奨しない」とされています。トランザクションの途中で再接続すると、セッションの状態やデータの整合性に影響するためです。

例5:TLS のバージョンが合わない

Caused by: javax.net.ssl.SSLHandshakeException: No appropriate protocol (protocol is disabled or cipher suites are inappropriate)

TLS 1.0・1.1 しか使えない以前の版の MySQL に、新しい Java から接続すると出ます。最近の Java は TLS 1.0・1.1 を既定で無効にしているためです。TLS 1.1 だけを許可した Java のクライアントで接続すると、同じメッセージになりました。

直し方 内容
MySQL を TLS 1.2 以上に対応させる(推奨) MySQL のバージョンを上げる、または TLS 1.2 を有効にする
接続URLで TLS のバージョンを指定 tlsVersions=TLSv1.2,TLSv1.3
TLS を使わない sslMode=DISABLED。社内ネットワークでも盗み見の危険があるため、検証環境以外では使わない

似ているが別のエラー

エラー文 原因 直し方
Access denied for user 'app'@'172.17.0.2' (using password: YES) ユーザー名・パスワード・接続元ホストの間違い(通信はできている) ユーザーとホストの組み合わせを確認
Host '...' is not allowed to connect to this MySQL server 接続元のホストが許可されていない ユーザーを接続元のホストで作る
Public Key Retrieval is not allowed caching_sha2_password の認証で、TLS を使わずに接続した TLS で接続する。検証環境なら allowPublicKeyRetrieval=true
Too many connections max_connections(既定 151)を超えた 接続プールの最大数の合計を見直す。接続を閉じ忘れていないか確認
Packet for query is too large max_allowed_packet を超える SQL・データ 一度に送るデータを分ける、または値を上げる

確認の手順(チェックリスト)

順番 確認すること コマンド・方法
1 2行目は「not received any packets」か「successfully received」か つながらないのか、途中で切れたのか
2 一番下の Caused by: 上の表で原因を絞る
3 アプリのマシンから DB のポートに届くか java Probe.java ホスト 3306、nc -vz ホスト 3306
4 MySQL の待ち受け ss -ltn | grep 3306、SHOW VARIABLES LIKE 'bind_address'
5 Docker なら接続先のホスト名 localhost になっていないか、サービス名か
6 途中で切れるなら、切断までの時間 wait_timeout、ネットワーク機器のタイムアウト、HikariCP の maxLifetime

よくある質問

Q. 朝いちばんの処理だけエラーになり、2回目からは動きます。 A. 夜間に使われなかった接続が、wait_timeout やネットワーク機器のタイムアウトで切られています(例4)。HikariCP の maxLifetime を、切られる時間より短くします。

Q. MySQL Workbench やコマンドからはつながるのに、アプリからだけつながりません。 A. 接続している場所が違うことが多い原因です。Workbench は自分のPCから、アプリはサーバーやコンテナから接続しています。アプリが動いているマシン(コンテナ)の中で Probe.java や nc を実行して確かめます。

Q. autoReconnect=true を付ければ直りますか。 A. Connector/J の説明では、この設定は推奨されていません。切れた接続を使った SQL はエラーになり、次のトランザクションから再接続する動きで、セッションの状態が失われます。接続プールの設定で対応します。

Q. MariaDB の JDBC ドライバでも同じですか。 A. エラーの文言は違いますが、原因と直し方の考え方(つながらないのか、途中で切れたのか、Caused by を見る)は同じです。

まとめ

  • Communications link failure は通信の失敗。SQL・パスワードの問題ではない
  • 2行目が「not received any packets」なら、一度もつながっていない。ポート・bind-address・Docker の localhost・ファイアウォールを調べる
  • 「successfully received ... milliseconds ago」や inactivity なら、途中で切れた。wait_timeout とネットワーク機器のタイムアウトを調べる
  • 一番下の Caused by: が本当の原因。Connection refused はポート、Connect timed out は経路
  • 途中で切れる問題は、HikariCP の maxLifetime を切断時間より短くして直す。autoReconnect には頼らない

参考・出典

確認日はいずれも 2026年10月10日です。

  • MySQL 8.0 Reference Manual「MySQL server has gone away」:https://dev.mysql.com/doc/refman/8.0/en/gone-away.html
  • MySQL Connector/J 9.7.0 ソース(メッセージの定義・接続プロパティの説明):https://github.com/mysql/mysql-connector-j
  • HikariCP(README の設定項目):https://github.com/brettwooldridge/HikariCP
  • Docker Docs「Control startup and shutdown order in Compose」:https://docs.docker.com/compose/how-tos/startup-order/

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「Communications link failureの原因と直し方|MySQL」

株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。

WE ARE HIRING

RJCで一緒に開発しながら、
成長を楽しみませんか?

RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!

  • 127日年間休日
  • 12時間平均残業時間
  • 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!

ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。

ABOUT RJC RJCがどんな会社か知る 考え方、研修、働き方、福利厚生、社員の前職まで。RJCのことが丸わかり! RJC丸わかりページへ JOB DESCRIPTION 仕事内容・待遇を見てみる 仕事内容、給与・待遇、選考の流れ。経験者も未経験も!応募前に知りたいこと、まとめました! 募集要項を見る ENTRY エントリーする エントリーは1〜2分・履歴書不要です。まずは話を聞いてみたい、という方でも歓迎です! エントリーフォームへ

RJCで一緒に開発しながら、 成長を楽しみませんか?