ERROR 2006 (HY000): MySQL server has gone away 和 ERROR 2013: Lost connection to MySQL server during query 是生產環境高頻錯誤。本文針對三大核心場景(空閒超時、大包/Blob、長連接複用)給出根因、配置修復、代碼層面預防與監控告警體系。
| 場景 | 典型錯誤碼 | 核心原因 | 關鍵配置 |
|---|---|---|---|
| 長時間空閒 / 批量任務 | 2006 / 2013 | 連接空閒超過 wait_timeout (默認 8h) 被服務端主動斷開 | wait_timeout, interactive_timeout |
| 大 SQL / Blob 字段 | 2006 / 2013 | 數據包超過 max_allowed_packet (默認 4MB/16MB) | max_allowed_packet |
| 單例/連接池長連接複用 | 2006 | 應用層持有連接超過 wait_timeout,再次使用時已被服務端關閉 | 連接池 validationQuery, testOnBorrow |
PHP/Python/Java 批量腳本運行數小時,中間無數據庫操作,再次執行 SQL 拋 2006。
[mysqld]
wait_timeout = 28800 # 8 小時 → 可改 86400 (24h) 或更大
interactive_timeout = 28800 # 交互式客戶端同步修改
SELECT 1 或 mysql_ping()。validationQuery=SELECT 1、testOnBorrow=true、testWhileIdle=true、timeBetweenEvictionRunsMillis=30000。插入大文本、圖片、Base64 字符串,單條 SQL > max_allowed_packet。
[mysqld]
max_allowed_packet = 64M # 視最大業務包調整,建議 16M-256M
# 客戶端同步設置
# JDBC: ?maxAllowedPacket=67108864
# PHP PDO: 無需額外設置(驅動自動協商)
# Python: 連接參數 max_allowed_packet=64*1024*1024
mysqldump 導出時 取消勾選「擴展插入」,生成單行 INSERT,避免超大包。mysqldump --skip-extended-insert。max_allowed_packet。// 危險:靜態單例連接,生命周期 = 進程生命周期
private static Connection conn = DriverManager.getConnection(url, user, pass);
# HikariCP (Java 標準)
spring.datasource.hikari.maximum-pool-size=20
spring.datasource.hikari.minimum-idle=5
spring.datasource.hikari.idle-timeout=300000 # 5 分鐘空閒回收
spring.datasource.hikari.max-lifetime=1800000 # 30 分鐘強制換新
spring.datasource.hikari.connection-timeout=30000
spring.datasource.hikari.validation-timeout=5000
spring.datasource.hikari.connection-test-query=SELECT 1 # 驗證查詢
# 或 DBCP2
validationQuery=SELECT 1
testOnBorrow=true
testWhileIdle=true
timeBetweenEvictionRunsMillis=60000
// mysql_* 函數無連接池,每次請求新建連接,自然無長連接問題
// 若用 mysqli 持久連接 (p: 前綴)
$mysqli = new mysqli('p:localhost', 'user', 'pass', 'db');
// 必須在每次使用前 ping
if (!$mysqli->ping()) {
$mysqli->close();
$mysqli = new mysqli('p:localhost', 'user', 'pass', 'db');
}
| 指標 | 來源 | 告警閾值 |
|---|---|---|
| Aborted_clients | SHOW GLOBAL STATUS | 持續增長 → 客戶端異常斷開 |
| Aborted_connects | SHOW GLOBAL STATUS | > 0 → 連接建立失敗 |
| Threads_connected / max_connections | SHOW GLOBAL STATUS / VARIABLES | > 80% → 連接池耗盡風險 |
| Max_used_connections | SHOW GLOBAL STATUS | 接近 max_connections → 歷史峰值過高 |
wait_timeout、max_allowed_packet,監控連接數。validationQuery + 重試邏輯。mysqldump --skip-extended-insert + 導入端大包配置。