MySQL 默認 wait_timeout=28800(8 小時),空閒連接超時被服務器主動斷開。應用層連接池若無驗證/重連機制,再次使用該連接會報錯 Communications link failure / MySQL server has gone away。本文給出服務端調大超時、應用端連接池驗證、雙向保障方案。
# /etc/my.cnf
[mysqld]
wait_timeout = 500000 # 約 5.8 天
interactive_timeout = 500000 # 交互式客戶端超時
# 或啟動參數
mysqld --wait_timeout=500000 --interactive_timeout=500000
修改後重啟驗證:
mysql> SHOW VARIABLES LIKE 'wait_timeout';
+---------------+--------+
| Variable_name | Value |
+---------------+--------+
| wait_timeout | 500000 |
+---------------+--------+
⚠️ 僅調大超時**治標不治本**,長時間空閒連接佔用服務器資源(線程、內存),極端情況導致 Too many connections。
| 連接池 | 驗證配置 | 推薦值 |
|---|---|---|
| HikariCP (Spring Boot 2 默認) | connectionTestQuery: SELECT 1 (JDBC4 可無,靠 isValid())minimumIdle, maximumPoolSize | 保持默認,確保 validationTimeout > 1000 |
| Druid (阿里) | validationQuery: SELECT 1testWhileIdle: truetimeBetweenEvictionRunsMillis: 60000 | 開啟空閒檢測,驅逐超時連接 |
| DBCP2 | validationQuery: SELECT 1testOnBorrow: true | 借用時驗證,影響獲取連接延遲 |
| c3p0 | preferredTestQuery: SELECT 1idleConnectionTestPeriod: 300 | 定期異步檢測空閒連接 |
wait_timeout = 86400(1 天),足覆蓋夜間低峰,避免無限堆積testWhileIdle=true / idleConnectionTestPeriod)+ **借用時驗證**(testOnBorrow=true / HikariCP 依賴 isValid())SELECT 1(極輕量、無副作用)maxLifetime < wait_timeout(HikariCP maxLifetime 默認 30 分鐘),主動回收老化連接
// 伪代碼:數據庫操作統一捕獲通信異常,重試一次
try {
return dao.query(sql);
} catch (CommunicationsException | SQLException e) {
if (isConnectionFailure(e)) {
log.warn("DB connection lost, retry once");
return dao.query(sql); // 連接池會提供新連接
}
throw e;
}
「服務端給足緩衝、應用端主動驗證、代碼層兜底重試」三層防線,徹底解決空閒連接斷開導致的業務報錯。