我有一个用于测试目的的小型 Java 应用程序。我最近搬到了 hikari。我注意到我不断收到此错误。
java.sql.SQLTransientConnectionException: HikariPool-1 - Connection is not available, request timed out after 30000ms.
java.sql.SQLTransientConnectionException: HikariPool-1 - Connection is not available, request timed out after 30000ms.
at com.zaxxer.hikari.pool.HikariPool.createTimeoutException(HikariPool.java:602)
at com.zaxxer.hikari.pool.HikariPool.getConnection(HikariPool.java:195)
at com.zaxxer.hikari.pool.HikariPool.getConnection(HikariPool.java:145)
at com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:85)
以下是我最初对 hikari 的设置。
HikariConfig config = new HikariConfig();
config.setJdbcUrl("jdbc:mysql://localhost:3306/****");
config.setUsername("***");
config.setPassword("*****");
config.setMaximumPoolSize(20);
我的两个设备几乎没有被使用,我确保最后我会关闭它。所以我不知道为什么它不断收到错误?可能是什么问题或者我需要更改一些设置吗?
我的 hikari 版本是 HikariCP-2.6.1.jar。
由于网络延迟或某些查询执行时间过长(超过 30000 毫秒),您的数据库未在(默认的 connectionTimeout 属性为 30000 毫秒)内获取连接。
请努力增加财产价值
connectionTimeout
。
YML配置示例:
spring:
datasource:
hikari:
minimumIdle: 2
maximumPoolSize: 10
idleTimeout: 120000
connectionTimeout: 300000
leakDetectionThreshold: 300000
Java 配置示例:
HikariConfig config = new HikariConfig();
config.setMaximumPoolSize(20);
config.setConnectionTimeout(300000);
config.setConnectionTimeout(120000);
config.setLeakDetectionThreshold(300000);
我正在使用 spring boot,我遇到了同样的问题,我的解决方案是获得像这样的连接“
DataSourceUtils.getConnection(dataSource)
”。所以我从dataSource.getConnection()
更改为DataSourceUtils.getConnection(dataSource)
。
在我的例子中,代码没有关闭连接。
尝试使用资源修复了它:
try (
Connection connection = dataSource.getConnection();
Statement statement = …
) {
…
}
在我的例子中,我使用 JPA,因此使用 EntityManagerFactory 来持久化和查询我的 springBoot 项目,并得到相同的错误。
原因是在任何 CRUD 操作中,一旦操作完成,我就不会关闭 EntityManager,从而耗尽资源。
希望这有帮助!
EntityManager em = emf.createEntityManager();
Customer c = em.find(Customer.class , id);
em.close();
请求超时不是可以通过增加超时来解决的问题。也许您需要评估服务中的所有查询并在需要时实施索引
如果客户端应用程序请求大量打开连接并且数据库服务器设置对池连接数有最大限制,也可能会发生这种情况。因此客户端应用程序无法从数据库服务器获取更多连接。检查数据库服务器连接池,看看在错误发生期间是否超出了最大连接数。
我已经使用以下方法解决了我的问题:
增加 minIdle 和 maxPool
spring.datasource.hikari.minimumIdle=20
spring.datasource.hikari.maximumPoolSize=30
spring.datasource.hikari.connectionTimeout=50000
要调试问题/检查值是否正常,请启用 Hikari 的日志记录:
logging.level.com.zaxxer.hikari.HikariConfig=DEBUG
logging.level.com.zaxxer.hikari=TRACE
日志将如下所示:
DEBUG 2023-01-06T16:12:31.932018849Z HikariPool-1 - Before cleanup stats (total=17, active=0, idle=17, waiting=0)
DEBUG 2023-01-06T16:12:31.932665522Z HikariPool-1 - After cleanup stats (total=17, active=0, idle=17, waiting=0)
DEBUG 2023-01-06T16:12:31.932733949Z HikariPool-1 - Fill pool skipped, pool is at sufficient level.
DEBUG 2023-01-06T16:12:32.495269726Z HikariPool-1 - After adding stats (total=17, active=0, idle=17, waiting=0)
DEBUG 2023-01-06T16:12:38.309953158Z HikariPool-1 - Fill pool skipped, pool is at sufficient level.
DEBUG 2023-01-06T16:12:39.200246897Z HikariPool-1 - Fill pool skipped, pool is at sufficient level.
DEBUG 2023-01-06T16:12:44.812065268Z HikariPool-1 - Before cleanup stats (total=18, active=0, idle=18, waiting=0)
DEBUG 2023-01-06T16:12:44.812822113Z HikariPool-1 - After cleanup stats (total=18, active=0, idle=18, waiting=0)
祝你好运! :)
警告: 请小心,较大的 MaximumPoolSize 可能会产生代码异味,并且可能隐藏性能问题,例如:长事务。 DB 供应商还建议使用较小的 MaximumPoolSize,例如:maximumPoolSize=10。数据库性能将受到较大的 MaximumPoolSize 值的影响。
花了很长时间才弄清楚......就我而言,我使用了类似于@Andres Rincon:
的解决方案try (Connection connection = DataSourceUtils.getConnection(jdbcTemplate.getDataSource())) {
// some code here
}
通常打开和未关闭的连接会导致此问题。连接数据库的应用程序服务器有限制,如果超过此限制,您的环境将会崩溃。
连接必须采用单例模式,但如果您确实需要打开数据源或连接外部数据源(例如报告),则必须在打开连接块的finally块中关闭连接
connection.getConnection().rollback();
connection.getConnection().close();
如果您使用没有单例的 PersistenceJpa,也必须关闭
persistenceJPAConfig.dataSource().getConnection().rollback();
persistenceJPAConfig.dataSource().getConnection().close();
如果您通过创建线程来使用一些压力测试工具来测试您的方法,您可能会在需要很长时间的查询上遇到此错误。它将引导优化您的查询或服务实例大小。
就我而言:
o.h.engine.jdbc.spi.SqlExceptionHelper: HikariPool-1 - Connection is not available, request timed out after 30019ms.
i.s.commons.web.error.ExceptionLogger: Internal Server Error
org.springframework.transaction.CannotCreateTransactionException: Could not open JPA EntityManager for transaction; nested exception is org.hibernate.exception.JDBCConnectionException: Unable to acquire JDBC Connection
是由于应用程序属性中的
spring.hikari.maximumPoolSize
太低引起的,从5
增加到20
解决了问题。
日志消息有点误导。
解决我的问题的方法是在正确的数据库表中添加正确的索引。查看您对数据库进行的查询/事务。
在我的例子中,导致延迟的语句是 UPDATE 语句,例如
UPDATE table_name WHERE column1 = value1, column2 = value2;
在这种情况下,为我解决问题的方法是在该表中为这两列添加索引,例如:
CREATE INDEX index_name ON table_name (column1, column2);
另一个很好的原因可能是你没有关闭你的连接。您可以使用 try-with-resource 语句关闭连接,例如:
try( Connection connection = datasource.getConnection() ){
//your code
}
在我看来,按照 Girdhar Singh Rathore 建议增加超时并不理想。它可以暂时解决问题,但在某些时候您需要注意正确的索引和关闭连接管理。
希望这有帮助。
在我的例子中,我使用了类似于@Andres Rincon的解决方案:
try (Connection conn = connectionManager.getDataConnection()) {
Statement stmt = conn.createStatement();
...
conn.close();
} catch (Exception e) {
e.printStackTrace();
}
在我的例子中,我将 hikaripoolConnection 的大小增加到 10,这个问题得到了解决。