当前位置: 首页 > 知识库问答 >
问题:

H2-Tomcat jdbc连接池在达到最大限制时不回收连接

滑弘扬
2023-03-14

问题陈述

我们在嵌入式模式下使用H2已有一段时间了。它上面配置了一个连接池。以下是当前池配置:

h2.datasource.min-idle=10
h2.datasource.initial-size=10
h2.datasource.max-active=200
h2.datasource.max-age=600000
h2.datasource.max-wait=3000
h2.datasource.min-evictable-idle-time-millis=60000
h2.datasource.remove-abandoned=true
h2.datasource.remove-abandoned-timeout=60
h2.datasource.log-abandoned=true
h2.datasource.abandonWhenPercentageFull=100

H2配置:

spring.h2.console.enabled=true
spring.h2.console.path=/h2
h2.datasource.url=jdbc:h2:file:~/h2/cartdb
h2.server.properties=webAllowOthers
spring.h2.console.settings.web-allow-others=true
h2.datasource.driver-class-name=org.h2.Driver

*跳过用户名和密码属性。

我们已经通过记录池属性验证了上述配置的有效性。

这个设置的问题是,我们观察到连接池经常(尽管是间歇性的)耗尽,一旦连接池达到最大限制,它就开始为一些查询抛出以下异常。

SqlExceptionHelper.log异常(SqlExceptionHelper.java:129)-[超文本传输协议-APR-8080-exec-38]超时:池为空。无法在3秒内获取连接,无可用[size: 200;繁忙: 200;空闲: 0; last等待: 3000]。

此后,即使在我们重新启动Web服务器(在本例中为tomcat)之前,它也无法从这种状态恢复。

H2驱动程序依赖关系:

<dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
    <version>1.4.196</version>
    <scope>runtime</scope>
</dependency>

查询模式

我们使用h2为每个请求加载一些数据,然后执行一些(大约50个)SELECT查询,最后删除数据。这导致在h2(根据new relic monitoring)上每分钟有30k-40k个呼叫(非工作时间除外)。

每个读取操作都会获取一个新连接,并在执行后释放该连接。

EntityManager entityManager = null;
try {
     entityManager = entityManagerFactory.createEntityManager();
     Query query = entityManager.createNativeQuery(sqlQuery);
     query.setParameter("cartId", cartId);
     List<String> resultList = query.getResultList();
     return resultList;
} finally {
         if(null != entityManager) { entityManager.close(); }
}

观察

  • 应用程序重新启动后,池利用率将降至最低,直到池利用率突然上升并最终达到最大限制。这种情况持续1-2天

请引导我们朝着正确的方向解决这个问题。

使现代化

最近,当发生这样的事件时,我们在堆栈跟踪中发现了以下原因:

原因:org。h2。jdbc。JdbcSQLException:数据库可能已在使用中:null。可能的解决方案:关闭所有其他连接;使用服务器模式[90020-196]

原因:java。lang.IllegalStateException:文件已锁定:nio:/root/h2/cartdb。mv。db[1.4.196/7]

引起:java.nio.channels.OverlappingFileLockExc0019

因此,在深入研究这一点之后,我们决定转向内存模式,因为我们不需要在应用程序的生命周期之外保存数据。因此,不应发生文件锁定,从而减少或消除此问题。

在任何情况下都会回来更新。

共有1个答案

魏臻
2023-03-14

自上次更新该问题以来:

在观察了相当一段时间的性能后,我们得出结论,在文件模式(嵌入式)中使用H2会周期性地导致文件锁定异常(尽管不规则)。

由于我们的应用程序不需要在应用程序的生命周期之后保存数据,因此我们决定转向纯内存模式。

尽管文件锁异常的神秘性仍然需要揭示。

 类似资料:
  • 我正在使用hikari cp和spring boot应用程序,它有超过1000个并发用户。我已经设置了最大池大小- 当我使用 它显示的最大值为300,等于池大小。它永远不会增加超过最大池。这是故意的吗?我认为池大小意味着保持连接,以便在将来需要数据库请求时可以重用连接,但在需要时可以进行更多连接。 另外,当我删除max pool配置时,我会立即得到- HikariPool-0-连接不可用,请求在3

  • 我在karaf中的pax-jdbc的池连接有问题,我试图通过blueprint.xml注入一个MySQL数据源(DS)到我的项目中,为了测试它,我已经建立了一个karaf命令,将DS注入karaf命令类并使用该连接执行查询。这是可以的,但是问题是当我执行命令很多次时,每次执行都会创建一个新的DS实例,并且池连接无法打开到MySQL的新连接,因为池已经达到极限。 我已通过以下链接将代码上传到gith

  • 嘿,我正在使用Glassfish开源v4,我遇到了一个奇怪的问题。 我在管理控制台中定义了到Oracle 11g的JDBC连接池,并设置了: 初始和最小池大小:500 最大游泳池大小:1000 池大小调整数量::750 我已经为这个连接池创建了一个特定的用户。然而,有时当我检查数据库中打开的连接时,我发现有1000多个连接(我看到的最大连接数是1440个) 当发生这种情况时,任何查询尝试都会失败,

  • 使用来自DBCP的BasicDataSource,如果我们执行getConnection()并且在最后一个块中我们关闭连接,它是真的将连接返回到池还是关闭连接。我正在检查的代码片段是这样的 我正在检查BasicDataSource的源代码,并访问了这个包装类以获取连接。 委托对象的类型为java。sql。联系包装器代码调用委托的close方法,该方法将关闭集合,而不是将连接返回到池。这是DBCP的

  • 在OkHttp中,我找不到设置硬最大连接池大小的方法。从留档https://square.github.io/okhttp/3.x/okhttp/okhttp3/ConnectionPool.html很明显,您可以设置最大空闲连接,但不能设置整体最大值。这意味着在高负载下,它可以增长超过任何限制。 有没有办法最大化池?如果没有,为什么没有?

  • 我正在尝试使用ApacheDBCP2使用连接池。 我的最大总连接是5。我关闭每一个连接后,它被使用。 但在连接池中关闭5次连接后,我仍然获得连接。 关闭5个连接后,何时ping数据库以获取连接?或者,它将从连接池本身获取数据,而不访问数据库。 下面是我的示例代码片段。请纠正我对连池的理解。