MYSQL執行SQL語句異常:The last packet successfully received from the server was 100,107 milliseconds ago. The last packet sent successfully to the server was 100,101 milliseconds ago.
這個錯誤表明 MySQL 服務器與 JDBC 連接之間的通信超時了。通常由以下幾種情況引起:
錯誤原因
長時間沒有交互(MySQL 服務器關閉了空閑連接)
MySQL 服務器的 wait_timeout 或 interactive_timeout 設置較短,導致長時間未使用的連接被關閉。
SQL 查詢執行時間過長
如果查詢運行時間超過 JDBC 連接的 socketTimeout,MySQL 驅動程序會終止連接。
網絡問題
服務器端或客戶端的網絡連接中斷,導致 JDBC 連接失敗。
MySQL 服務器崩潰或重啟
服務器重啟后,原來的連接失效,導致客戶端報錯。
解決方案
? 方法 1:增加 MySQL wait_timeout 和 interactive_timeout
執行以下 SQL 命令,查看 MySQL 服務器的超時時間:
SHOW VARIABLES LIKE 'wait_timeout';
SHOW VARIABLES LIKE 'interactive_timeout';
如果值較小(例如 28800 秒以下),可以嘗試增加:
SET GLOBAL wait_timeout = 28800;
SET GLOBAL interactive_timeout = 28800;
?? 注意:此修改對現有連接無效,僅對新連接生效。如果需要持久生效,請修改 my.cnf 或 my.ini 配置:
[mysqld]
wait_timeout=28800
interactive_timeout=28800
然后重啟 MySQL 服務器。
? 方法 2:在 JDBC 連接 URL 中添加 autoReconnect=true&socketTimeout
修改 JDBC 連接 URL,設置自動重連和超時:
String url = "jdbc:mysql://localhost:3306/testdb?autoReconnect=true&socketTimeout=60000";
Connection conn = DriverManager.getConnection(url, user, password);
autoReconnect=true:當連接丟失時,自動重新連接(?? MySQL 8+ 已不推薦使用)。
socketTimeout=60000:設置 socket 超時時間為 60 秒,防止過早斷開。
? 方法 3:使用 keep-alive 保持連接
如果 MySQL 連接長時間空閑,MySQL 服務器可能會斷開連接。可以使用 HikariCP 或 Druid 連接池,每隔一段時間發送 ping 保持連接。
HikariCP 連接池配置
HikariConfig config = new HikariConfig();
config.setJdbcUrl("jdbc:mysql://localhost:3306/testdb");
config.setUsername("root");
config.setPassword("password");
config.setMaximumPoolSize(10);
config.setMinimumIdle(2);
config.setIdleTimeout(30000); // 30 秒空閑超時
config.setKeepaliveTime(15000); // 每 15 秒發送 keep-alive
HikariDataSource dataSource = new HikariDataSource(config);
keepaliveTime=15000:每 15 秒發送一個 ping,防止連接超時。
Druid 連接池配置
DruidDataSource dataSource = new DruidDataSource();
dataSource.setUrl("jdbc:mysql://localhost:3306/testdb");
dataSource.setUsername("root");
dataSource.setPassword("password");
dataSource.setMinIdle(5);
dataSource.setMaxActive(10);
dataSource.setValidationQuery("SELECT 1");
dataSource.setTestWhileIdle(true);
dataSource.setTimeBetweenEvictionRunsMillis(30000); // 30 秒檢測一次
validationQuery=“SELECT 1”:連接池在連接空閑時,發送 SELECT 1 測試連接是否可用。
? 方法 4:檢查 MySQL 服務器狀態
如果服務器已經重啟或崩潰,嘗試重啟 MySQL:
sudo systemctl restart mysql # Linux
net stop mysql && net start mysql # Windows
總結
還可以結合 連接池 + socketTimeout + keepalive 方式,來確保 JDBC 連接的穩定性。