專案使用 Hibernate 3 + MySQL 4.0 + JDBC 驅動 3.0.9,部署次日即出現 No operations allowed after connection closed,重啟 Tomcat 暫時恢復,隔天復發。根因是 MySQL 預設 wait_timeout=8小時 閒置斷開連線,而 Hibernate 內建連接池無檢測機制,導致池中連線失效。本文記錄三種嘗試方案,最終以 C3P0 連接池徹底解決。
No operations allowed after connection closedwait_timeout=28800秒(8小時) 後自動斷開閒置連線autoReconnect=true ❌jdbc:mysql://host:3306/db?autoReconnect=true
結果:無效。官方文檔明確不建議生產環境使用,且 Hibernate 連接池不觸發重連邏輯。
Session session = sessionFactory.openSession();
if (!session.isConnected()) {
session.reconnect(); // 或重新 openSession
}
結果:無效。Hibernate Session 狀態判斷不可靠,且業務碼侵入性強,難以全面覆蓋。
hibernate_install_dir/lib/c3p0-0.8.3.jar 至專案 lib/hibernate.properties 取消註釋 hibernate.c3p0.* 相關配置(或自訂):hibernate.c3p0.min_size=5
hibernate.c3p0.max_size=20
hibernate.c3p0.timeout=1800 -- 連線最大閒置秒數,小於 MySQL wait_timeout
hibernate.c3p0.idle_test_period=300 -- 每 5 分鐘檢測一次閒置連線
hibernate.c3p0.preferred_test_query=SELECT 1 -- 檢測查詢
hibernate.c3p0.acquire_increment=3
| 參數 | 建議值 | 作用 |
|---|---|---|
| hibernate.c3p0.timeout | 1800 (30分) | 連線在池中最大閒置時間,**必須 < MySQL wait_timeout** |
| hibernate.c3p0.idle_test_period | 300 (5分) | 定期檢測閒置連線活性,配合 preferred_test_query |
| hibernate.c3p0.max_statements | 50~100 | PreparedStatement 快取大小,提升效能 |
| hibernate.c3p0.acquire_increment | 3~5 | 池擴容步長,避免頻繁建連 |
原代碼存在「單 Session 多請求複用」問題,已重構為「請求級 Session:Open → 用完 Close」,配合 C3P0 連接池,雙重保障穩定性。
以 C3P0 替換內建池,配置合理的閒置檢測策略,是解決 MySQL 8 小時斷連問題的標準答案。