應用長時間閒置後再次操作資料庫,拋出 Communications link failure / The last packet successfully received ... was 43200 milliseconds ago,根因是 MySQL wait_timeout (預設 8 小時) 切斷閒置連線,而連線池未偵測失效繼續借出舊連線。
核心參數
| 參數 | 預設值 | 含義 |
wait_timeout | 28800 (8h) | 非互動式連線閒置超時秒數 |
interactive_timeout | 28800 | 互動式連線 (mysql client) 閒置超時 |
max_allowed_packet | 4M/64M | 封包大小上限,過小也會斷線 |
三大解決策略 (擇一或組合)
策略一:連線池驗證機制 (推薦、治本)
# HikariCP (Spring Boot 2.x 預設)
spring.datasource.hikari.connection-timeout=30000
spring.datasource.hikari.idle-timeout=600000
spring.datasource.hikari.max-lifetime=1800000
spring.datasource.hikari.connection-test-query=SELECT 1
spring.datasource.hikari.validation-timeout=5000
# c3p0 (Hibernate 傳統)
hibernate.c3p0.testConnectionOnCheckout=true
hibernate.c3p0.preferredTestQuery=SELECT 1
hibernate.c3p0.idle_test_period=300
核心:借出連線前執行 SELECT 1 驗證存活,失效則重建。
策略二:縮短應用端存活時間 < MySQL wait_timeout
- 設定連線池
maxLifetime (Hikari) / maxIdleTime (Druid) 小於 wait_timeout (如 30 分鐘)。
- 定時回收閒置連線,避免借到已被 Server 斷開的連線。
策略三:JDBC URL 啟用自動重連 (治標、慎用)
jdbc:mysql://host:3306/db?autoReconnect=true&useUnicode=true&characterEncoding=UTF-8
缺點:可能掩蓋事務邊界、導致資料不一致、不支援 XA 事務,生產環境不建議單獨依賴。
最佳實務組合拳
- MySQL 端:
wait_timeout=7200 (2h) / interactive_timeout=7200。
- 連線池端:
maxLifetime=1800000 (30min) + connectionTestQuery=SELECT 1。
- 應用端:捕獲
SQLTransientConnectionException 重試邏輯 (指數退避)。
- 監控:
SHOW GLOBAL STATUS LIKE 'Aborted_connects'; 趨勢上升即告警。
連線斷開本質是「雙端生命週期不一致」,以連線池主動驗證為核心、雙端超時配合為輔,可徹底根治。
- 上一篇文章: MySQL 計算欄位實戰:CONCAT 串聯、算術運算、別名與測試技巧
- 下一篇文章: Windows 環境 MySQL 忘記 root 密碼重置完整步驟 (含 --skip-grant-tables 模式)
Copyright ©
程式碼之家 All Rights Reserved