錯誤 `2006 - MySQL server has gone away` 表示客戶端與伺服器的連線意外中斷。常見於大量資料匯入、長時間查詢、網路不穩等場景。
[Err] 2006 - MySQL server has gone away
場景:`mysqldump` 匯入大 SQL、批次 INSERT 超長、大欄位(BLOB/JSON)寫入。
檢查當前值:
SHOW VARIABLES LIKE 'max_allowed_packet';
解決:
場景:應用連線池連線閒置超過 `wait_timeout` (預設 8小時),伺服器主動斷開,應用再用時拋錯。
解決:
排查:
| 現象 | 可能原因 | 驗證方式 |
|---|---|---|
| 匯入大 SQL 失敗 | max_allowed_packet 過小 | 檢查 SQL 單行長度 > 當前值 |
| 晨間首次請求失敗 | 連線池閒置超時 | 錯誤發生時間 ≈ 最後活動 + wait_timeout |
| 所有連線同時斷開 | MySQL 重啟/崩潰 | error.log 有啟動/關閉記錄、Uptime 歸零 |
| 特定大查詢失敗 | 查詢耗時 > net_read_timeout | 優化查詢或調大 net_read_timeout |
# Python (PyMySQL) 範例
import pymysql
from pymysql.err import OperationalError
import time
def execute_with_retry(sql, max_retries=3):
for attempt in range(max_retries):
try:
with conn.cursor() as cursor:
cursor.execute(sql)
return cursor.fetchall()
except OperationalError as e:
if e.args[0] in (2006, 2013): # Gone away / Lost connection
if attempt == max_retries - 1:
raise
time.sleep(2 ** attempt) # 指數退避
conn.ping(reconnect=True) # 重連
else:
raise
[mysqld]
max_allowed_packet = 256M # 根據最大業務欄位預留
wait_timeout = 28800 # 8小時,配合應用層驗證
interactive_timeout = 28800
net_read_timeout = 60 # 跨機房可調 300
net_write_timeout = 60
innodb_buffer_pool_size = 70% RAM # 減少磁碟 IO 導致的查詢超時