應用程式(如 PHP 批次腳本、圖片資料處理)執行長時間或大型 SQL 時,MySQL 突然斷開連線,拋出 MySQL server has gone away(錯誤碼 2006)。
max_allowed_packet典型場景:超長 SQL、含 BLOB/LONGBLOB 欄位(如圖片二進制)、大批次 INSERT。
解決:調大 my.cnf 參數:
[mysqld]
max_allowed_packet = 64M # 視實際需求調整,建議 16M-256M
重啟 MySQL 生效。原理:此參數控制通訊緩衝區上限,客戶端與伺服端均需足夠大。
wait_timeout典型場景:應用使用連線池/單例模式,兩次 DB 操作間隔超過 wait_timeout(預設 8 小時 = 28800 秒),MySQL 主動斷開閒置連線,應用重用失效連線時報錯。
驗證:SHOW VARIABLES LIKE 'wait_timeout';
[mysqld]
wait_timeout = 2880000
interactive_timeout = 2880000
程式碼層面定期執行 mysql_ping() 或輕量查詢(如 SELECT 1),維持連線活躍。
-- 連線建立後立即執行
SET SESSION interactive_timeout = 86400; -- 24小時
最佳實踐:連線池配置testOnBorrow=true+validationQuery=SELECT 1,借用連線前自動驗證,失效則重建。
| 成因 | 徵兆 | 對策 |
|---|---|---|
| MySQL 進程崩潰 | 錯誤日誌有 Assertion failure、Signal 11 | 檢查核心轉儲、升級版本、排查硬體 |
| 客戶端庫版本不匹配 | 升級 MySQL 後未重編譯客戶端 | 重編譯/更新連接器 |
| 伺服端主動 KILL | 管理員執行 KILL、超時殺進程腳本 | 排查殺進程邏輯、調整閾值 |
| 網路設備斷開閒置連線 | 防火牆/NAT 超時(通常 30-60 分鐘) | 啟用 TCP Keepalive、應用層心跳 |
mysqli 或 PDO 替代已棄用的 mysql 擴展PDO::ATTR_PERSISTENT => false(避免持久連線超時坑)+ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTIONset_time_limit(0) + 分批提交 + 定期 $pdo->query('SELECT 1') 心跳