MySQLのエラー『エラー2006: MySQL Server Has Gone Away』の解決方法

MySQLのエラー『エラー2006: MySQL Server Has Gone Away』の解決方法

MySQLで「MySQL Server Has Gone Away(エラーコード2006)」というエラーが発生するのは、サーバーとの接続が切断されたことを意味している。これは多くの原因で起こるため、再現条件や対応方法を明確に特定することが重要。長時間の接続維持、大きなクエリ送信、パケットサイズ超過、タイムアウトなどの要因が重なると頻出する。

1. エラーが発生する主な条件

  • MySQLがクライアントの接続をタイムアウトした
  • 非常に大きなクエリやデータ(BLOBなど)を送信し、パケットサイズ制限を超えた
  • 不正または不完全なSQL文を送信した
  • MySQLサーバーの再起動やクラッシュ

2. エラーメッセージの例

ERROR 2006 (HY000): MySQL server has gone away

このエラーはMySQLクライアントやプログラムで発生し、接続を再利用しようとしたときにサーバーから応答がないことで返される。

3. クエリが大きすぎる場合の対処方法

BLOBや長大なINSERT文を扱う際には、MySQLの最大パケットサイズを超えると接続が切断される。

SET GLOBAL max_allowed_packet = 1073741824; -- 1GB

通常の設定では16MB(16777216)になっている。必要に応じて `my.cnf` に以下を追加。

[mysqld]
max_allowed_packet=256M

4. 接続のタイムアウト対策

長時間処理し続けるスクリプトや非同期処理では、接続タイムアウトが問題になる。

[mysqld]
wait_timeout = 28800
interactive_timeout = 28800

短すぎるとクライアントが接続を保持していてもサーバー側が切断してしまう。

5. サーバー側のクラッシュや再起動の影響

MySQLサーバーが何らかの理由で再起動またはクラッシュした場合も同様のエラーが発生する。サーバーログ `/var/log/mysql/error.log` や `dmesg` を確認して、OOMキラーやメモリエラー、ディスク障害の兆候を確認する。

6. SQL文が不正な場合の再現例

文法ミスや壊れた構文も「gone away」として返される場合がある。

INSERT INTO users VALUES ('aaa', 'bbb',  -- カッコ閉じ忘れなど

クエリ送信が完了せず、接続断とみなされる。

7. 接続再試行を行うアプリケーション設計

PHPやNode.jsなどのアプリケーションでは、接続が失われた際に自動再接続処理を加えることでエラー回避が可能。

PHP (PDO) での例:

try {
  $dbh = new PDO($dsn, $user, $pass);
  $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
  // 再試行ロジック
} catch (PDOException $e) {
  if (strpos($e->getMessage(), 'server has gone away') !== false) {
    // 再接続処理
  }
}

8. デーモンやバッチ処理の長時間接続対策

バッチやデーモンが長時間MySQL接続を維持するケースでは、定期的に接続を更新したり、Pingを送信することで切断を防ぐ。

$conn->ping(); // mysqliや一部のORMで使用可

9. my.cnfの設定を再確認する

MySQLの設定ファイル my.cnf をチェックし、以下のようなパラメータを調整する。

[mysqld]
max_allowed_packet=256M
wait_timeout=28800
net_read_timeout=60
net_write_timeout=60

変更後はMySQLを再起動する。

10. クライアント側のタイムアウト設定も確認

MySQLクライアントやORM、アプリケーションフレームワーク側でもタイムアウトが短く設定されていると、処理中に切断されることがある。

たとえば Node.js の mysql2 モジュールでの設定:

const connection = mysql.createConnection({
  host: 'localhost',
  user: 'root',
  password: '',
  database: 'test',
  connectTimeout: 10000
});

11. 通信の途中での切断(ネットワーク的な問題)

VPN経由やリバースプロキシ越しの接続では、途中でネットワーク切断が発生している可能性もある。iptablesやNginxのタイムアウト設定、あるいはTCP Keepaliveの設定も確認する。

12. 特定のSQLを疑う(特にLOAD DATAや大規模INSERT)

`LOAD DATA INFILE` や巨大な `INSERT INTO … VALUES …` を実行している際に発生するなら、クエリ自体を分割することで対処できる。

-- 悪い例(巨大なINSERT)
INSERT INTO logs VALUES (...), (...), (...), ... -- 数千行

-- 良い例(分割して複数回送信)
INSERT INTO logs VALUES (...);
INSERT INTO logs VALUES (...);