我创建了一个简单的程序,该程序使用HikariCP(连接池,https://github.com/brettwooldridge/HikariCP)连接到MariaDB数据库。只要连接不会闲置超过5分钟,一切都会正常进行。闲置5分钟后,所有查询将失败,并引发以下错误:
[JDA MainWS-ReadThread] WARN com.zaxxer.hikari.pool.PoolBase - HikariPool-1 - Failed to validate connection org.mariadb.jdbc.MariaDbConnection@2b6d3853 (Connection.setNetworkTimeout cannot be called on a closed connection). Possibly consider using a shorter maxLifetime value.
java.sql.SQLTransientConnectionException: HikariPool-1 - Connection is not available, request timed out after 30025ms.
at com.zaxxer.hikari.pool.HikariPool.createTimeoutException(HikariPool.java:697)
at com.zaxxer.hikari.pool.HikariPool.getConnection(HikariPool.java:196)
at com.zaxxer.hikari.pool.HikariPool.getConnection(HikariPool.java:161)
at com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:100)
at net.cubeverse.cvdiscordbot.database.Database.getConnection(Database.java:45)
at net.cubeverse.cvdiscordbot.database.DiscordVerifyDAO.isVerified(DiscordVerifyDAO.java:81)
at net.cubeverse.cvdiscordbot.command.discord.VerifyCommand.execute(VerifyCommand.java:25)
at net.cubeverse.cvdiscordbot.core.command.manager.CommandManager.executeDiscordCommand(CommandManager.java:34)
at net.cubeverse.cvdiscordbot.listeners.MessageListeners.onPrivateMessageReceived(MessageListeners.java:21)
at net.dv8tion.jda.core.hooks.ListenerAdapter.onEvent(ListenerAdapter.java:397)
at net.dv8tion.jda.core.hooks.InterfacedEventManager.handle(InterfacedEventManager.java:84)
at net.dv8tion.jda.core.handle.MessageCreateHandler.handleInternally(MessageCreateHandler.java:111)
at net.dv8tion.jda.core.handle.SocketHandler.handle(SocketHandler.java:37)
at net.dv8tion.jda.core.requests.WebSocketClient.onDispatch(WebSocketClient.java:868)
at net.dv8tion.jda.core.requests.WebSocketClient.onEvent(WebSocketClient.java:766)
at net.dv8tion.jda.core.requests.WebSocketClient.handleEvent(WebSocketClient.java:745)
at net.dv8tion.jda.core.requests.WebSocketClient.onBinaryMessage(WebSocketClient.java:903)
at com.neovisionaries.ws.client.ListenerManager.callOnBinaryMessage(ListenerManager.java:368)
at com.neovisionaries.ws.client.ReadingThread.callOnBinaryMessage(ReadingThread.java:270)
at com.neovisionaries.ws.client.ReadingThread.handleBinaryFrame(ReadingThread.java:990)
at com.neovisionaries.ws.client.ReadingThread.handleFrame(ReadingThread.java:749)
at com.neovisionaries.ws.client.ReadingThread.main(ReadingThread.java:108)
at com.neovisionaries.ws.client.ReadingThread.runMain(ReadingThread.java:64)
at com.neovisionaries.ws.client.WebSocketThread.run(WebSocketThread.java:45)
Caused by: java.sql.SQLException: Connection.setNetworkTimeout cannot be called on a closed connection
at org.mariadb.jdbc.internal.util.exceptions.ExceptionMapper.getSqlException(ExceptionMapper.java:277)
at org.mariadb.jdbc.MariaDbConnection.setNetworkTimeout(MariaDbConnection.java:1700)
at com.zaxxer.hikari.pool.PoolBase.setNetworkTimeout(PoolBase.java:552)
at com.zaxxer.hikari.pool.PoolBase.isConnectionAlive(PoolBase.java:168)
at com.zaxxer.hikari.pool.HikariPool.getConnection(HikariPool.java:185)
... 22 more
代码(连接到数据库并检索连接)
我使用以下代码建立连接,并通过#getConnection()返回它。我已经尝试过使用maxLifetime进行试验,但是无法解决问题。我还检查了MySQL超时设置,以确保maxLifetime连接短于wait_timeout。
public class Database {
private final HikariDataSource hikari;
public Database() {
// Setting up the hikari config
HikariConfig hikariConfig = new HikariConfig();
hikariConfig.setJdbcUrl("jdbc:mysql://ip:port/database");
hikariConfig.setUsername("xxxxx");
hikariConfig.setPassword("xxxxx");
hikariConfig.addDataSourceProperty("cachePrepStmts", "true");
hikariConfig.addDataSourceProperty("prepStmtCacheSize", "250");
hikariConfig.addDataSourceProperty("prepStmtCacheSqlLimit", "2048");
hikariConfig.addDataSourceProperty("useServerPrepStmts", "true");
hikariConfig.addDataSourceProperty("useLocalSessionState", "true");
hikariConfig.addDataSourceProperty("rewriteBatchedStatements", "true");
hikariConfig.addDataSourceProperty("cacheResultSetMetadata", "true");
hikariConfig.addDataSourceProperty("cacheServerConfiguration", "true");
hikariConfig.addDataSourceProperty("elideSetAutoCommits", "true");
hikariConfig.addDataSourceProperty("maintainTimeStats", "false");
hikariConfig.addDataSourceProperty("maxLifetime", "600000");
// Source: https://github.com/brettwooldridge/HikariCP/wiki/MySQL-Configuration
// Initialize a new hikari object
hikari = new HikariDataSource(hikariConfig);
}
public Connection getConnection() {
try {
System.out.println(S.INFO.getPrefix() + "Successfully established the database connection.");
return hikari.getConnection();
} catch (SQLException e) {
System.out.println(S.ERROR.getPrefix() + "Failed to establish the database connection.");
e.printStackTrace();
}
return null;
}
}
超时设置
我正在运行默认超时设置:
+----------------------------+----------+
| Variable_name | Value |
+----------------------------+----------+
| connect_timeout | 10 |
| delayed_insert_timeout | 300 |
| innodb_lock_wait_timeout | 50 |
| innodb_rollback_on_timeout | OFF |
| interactive_timeout | 28800 |
| lock_wait_timeout | 31536000 |
| net_read_timeout | 30 |
| net_write_timeout | 60 |
| slave_net_timeout | 3600 |
| thread_pool_idle_timeout | 60 |
| wait_timeout | 28800 |
+----------------------------+----------+
环境
JDK version : 1.8.0_111
Database : 5.5.60-MariaDB
Driver version : 2.4.2 (org.mariadb.jdbc.mariadb-java-client)
OS: : Linux CentOS 7
我还在GitHub
上的HikariCP存储库中打开了一个问题