使用 MySQL 時,最讓開發者頭疼的莫過於間歇性出現的連接異常。典型錯誤堆疊如下(以 Hibernate 為例):
org.hibernate.util.JDBCExceptionReporter - SQL Error:0, SQLState: 08S01 The last packet successfully received from the server was 43200 milliseconds ago... ... longer than the server configured value of 'wait_timeout'... com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Connection.close() has already been called.
MySQL 設有 wait_timeout 參數(預設 28800 秒,即 8 小時)。當客戶端連接閒置超過此時長,Server 端會主動斷開連接以釋放資源。然而,連接池或應用層仍持有這個已失效的連接對象,再次使用時便拋出異常。
修改 my.cnf:wait_timeout=31536000(一年)。但 Server 端最大識別值約 21 天,且長連接佔用資源,不推薦作為長期方案。
在借用連接前驗證連接存活。以 C3P0 連接池 + Hibernate 為例,關鍵配置:
<property name="hibernate.c3p0.testConnectionOnCheckout">true</property>
此屬性確保每次從池中取出連接時執行 SELECT 1 等輕量查詢驗證。雖有微小效能損耗,但換來穩定性極具性價比。
SELECT 1)autoReconnect=true(不推薦生產環境,有數據一致性風險)testConnectionOnCheckout 或 idleConnectionTestPeriodSQLException 並實現重試邏輯徹底理解 wait_timeout 機制,在連接池層面建立「自愈」能力,才是解決此類問題的正道。