長時間運行的伺服器程式(如 Java、Go、Python 後端服務)常面臨一個經典問題:資料庫連線在閒置 8 小時後被 MySQL 主動斷開,導致後續查詢拋出「Communications link failure」或「MySQL server has gone away」異常。本文深入解析機制、查詢現狀,並提供三種解決策略。
MySQL 預設將閒置連線的存活時間設為 28800 秒(8 小時),對應系統變數 wait_timeout。當連線閒置超過此值,Server 會自動切斷該連線。
mysql> SHOW VARIABLES LIKE '%timeout%';
關鍵輸出範例:
+-------------------+-------+ | Variable_name | Value | +-------------------+-------+ | wait_timeout | 28800 | | interactive_timeout | 28800 | +-------------------+-------+
mysql> SHOW PROCESSLIST;
Time 欄位顯示該連線已閒置秒數;當其超過 wait_timeout,連線即會被終止。若在 8 小時內執行任意 SQL,計時器會歸零重算。
現代連線池(HikariCP、Druid、DBCP2 等)皆支援 keepalive 或 testOnBorrow / testWhileIdle 設定,定期發送輕量查詢(如 SELECT 1)維持連線活躍。此為應用層解決,不依賴資料庫設定,最穩健。
修改 my.cnf:
[mysqld] wait_timeout = 31536000 # 1 年(單位:秒) interactive_timeout = 31536000
重啟 MySQL 後生效。缺點:佔用更多連線資源,若應用端連線洩漏,會加速耗盡 max_connections。
在 DAO 層或資料庫存取封裝中捕捉「連線中斷」異常,自動重新取得連線並重試查詢。需注意冪等性,避免非查詢操作重複執行。
Communications link failure 或 MySQL server has gone away。SHOW PROCESSLIST 中該連線消失。testWhileIdle + timeBetweenEvictionRunsMillis 定期心跳檢查。wait_timeout 適度調大(如 24 小時),減少極端情況下的斷線。妥善處理長連線維護,是打造高可用後端服務的關鍵基石之一。