MySQL server has gone away (CR_SERVER_GONE_ERROR) 表示客戶端與服務器的連接已斷開。核心原因只有兩類:連接空閒超時被服務器主動斷開、數據包超過 max_allowed_packet 被服務器拒絕。
wait_timeout(默認 8 小時 = 28800 秒)。[mysqld]
wait_timeout=86400 # 24 小時
interactive_timeout=86400
testOnBorrow=true + validationQuery=SELECT 1(Druid/HikariCP)。SELECT 1 保活。SET SESSION wait_timeout=86400;
SET SESSION interactive_timeout=86400;
或連接時指定 CLIENT_INTERACTIVE 标志(PHP mysql_connect(..., CLIENT_INTERACTIVE)、JDBC connectionProperties=interactiveClient=true)。INSERT ... VALUES (...),(...),... 累積過大。mysqldump 導出/導入時單行過長。[mysqld]
max_allowed_packet=256M # 視業務最大字段調整,建議 64M-1G
SET GLOBAL max_allowed_packet=268435456; -- 256MB
SET SESSION max_allowed_packet=268435456;
max_allowed_packet / 2)。setBinaryStream、PHP PDO::PARAM_LOB)。# 導出時不使用 --opt(默認開啟 extended-insert),改用完整 INSERT
mysqldump --skip-extended-insert --max-allowed-packet=256M db > dump.sql
# 導入時調大客戶端限制
mysql --max-allowed-packet=256M db < dump.sql
tail -f /var/log/mysql/error.log 找 Assertion failure、Signal 11、Out of memory。dmesg -T | grep -i mysql 看是否 OOM Killer 殺進程。net.ipv4.tcp_keepalive_time=600)、應用層重試。| 步驟 | 命令/操作 | 判斷依據 |
|---|---|---|
| 1 | SHOW GLOBAL VARIABLES LIKE 'wait_timeout'; | 是否過小(< 1 小時) |
| 2 | SHOW GLOBAL VARIABLES LIKE 'max_allowed_packet'; | 是否小於業務最大包 |
| 3 | 檢查錯誤日志近期是否有 crash/assert/oom | 服務端自殺 |
| 4 | 抓包/日志確認斷開前最後一條 SQL 大小 | 包過大 |
| 5 | 檢查中間網絡設備超時設置 | 網絡層斷開 |
wait_timeout=86400、max_allowed_packet=256M、innodb_buffer_pool_size 足夠防 OOM。maxLifetime < wait_timeout(如 30 分鐘)、閒置連接定期檢測。Communications link failure/CR_SERVER_GONE_ERROR 異常,實現指數退避重試(最多 3 次)。「Server has gone away」90% 由 空閒超時 或 包過大 引起。通過「服務端調大參數 + 連接池驗證 + 應用層重試」三層防禦,可徹底消除該錯誤。若排除上述仍頻發,必須檢查服務器硬件資源與錯誤日志,排查崩潰根因。