首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

Spring + MySQL 「8 小時斷連」徹底解決:連接池心跳檢查、驗證查詢、驅動參數三管齊下

     編輯:程式設計綜合問答

錯誤特徵:應用啟動正常,隔天早上第一波請求噴 `Communications link failure / No operations allowed after connection closed`,重啟 Tomcat 即恢復——經典的 MySQL `wait_timeout` 預設 8 小時 (28800 秒) 主動斷開閒置連接。

根因

連接池 (DBCP/HikariCP/Tomcat JDBC Pool) 借出的連接長時間未使用,MySQL Server 端已關閉 TCP 連線,連接池不知情,下次借用時直接拿失效連接執行 SQL,拋出 `SocketException`。

三層防禦體系(缺一不可)

層級配置關鍵推薦值
連接池心跳`testWhileIdle=true`
`timeBetweenEvictionRunsMillis=30000`
`minEvictableIdleTimeMillis=1800000` (30分)
每 30 秒掃描閒置連接,閒置超過 30 分驅逐
借用前驗證`testOnBorrow=true`
`validationQuery=SELECT 1`
`validationQueryTimeout=3`
每次 `getConnection()` 執行輕量查詢,失敗則丟棄重建
驅動層自動重連JDBC URL 附加:
`?autoReconnect=true&useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Taipei`
驅動偵測斷線自動重連 (僅適用舊版驅動 5.1.x,8.0+ 已棄用,靠連接池即可)

主流連接池範例

HikariCP (Spring Boot 2.x 預設)

spring.datasource.hikari:
  minimum-idle: 5
  maximum-pool-size: 20
  idle-timeout: 300000          # 5 分鐘
  max-lifetime: 1800000         # 30 分鐘,必須 < MySQL wait_timeout
  connection-timeout: 30000
  connection-test-query: SELECT 1
  validation-timeout: 3000

Tomcat JDBC Pool (傳統 XML)

<Resource name="jdbc/mydb"
  factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
  type="javax.sql.DataSource"
  driverClassName="com.mysql.cj.jdbc.Driver"
  url="jdbc:mysql://localhost:3306/mydb?serverTimezone=Asia/Taipei"
  username="root" password="pwd"
  testWhileIdle="true"
  timeBetweenEvictionRunsMillis="30000"
  minEvictableIdleTimeMillis="1800000"
  testOnBorrow="true"
  validationQuery="SELECT 1"
  validationQueryTimeout="3"
  maxActive="20" maxIdle="10" minIdle="5" />

驗證成效

  1. 啟動應用,`SHOW PROCESSLIST` 確認連接數。
    2. 睡眠 9 小時 (或將 MySQL `wait_timeout` 暫設 60 秒測試)。
    3. 發送請求,觀察日誌無異常、回應正常。
    4. `SHOW PROCESSLIST` 連接數應維持在池大小範圍,無大量 `Sleep` 累積。

配好上述三層,徹底告別「每天早上重啟一次」的惡夢。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved