Java H2-Tomcat jdbc连接池在达到最大限制时不回收连接
问题陈述 我们在嵌入式模式下使用H2已有一段时间了。它上面配置了一个连接池。以下是当前池配置:Java H2-Tomcat jdbc连接池在达到最大限制时不回收连接,java,tomcat,h2,jdbc-pool,Java,Tomcat,H2,Jdbc Pool,问题陈述 我们在嵌入式模式下使用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.dataso
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
*跳过用户名和密码属性
我们已经通过记录池属性验证了上述配置的有效性
这个设置的问题是,我们观察到连接池经常(尽管是间歇性的)耗尽,一旦连接池达到最大限制,它就开始为一些查询抛出以下异常
LogExceptionHelper(SqlExceptionHelper.java:129)-[http-apr-8080-exec-38]超时:池为空。无法在3秒钟内获取连接,无可用连接[大小:200;忙:200;空闲:0;上次等待:3000]
此后,即使在我们重新启动web服务器(本例中为tomcat)之前的许多小时,它也无法从这种状态恢复
H2驱动程序依赖关系:
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.196</version>
<scope>runtime</scope>
</dependency>
com.h2数据库
氢
1.4.196
运行时
查询模式和吞吐量
我们使用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(); }
}
EntityManager EntityManager=null;
试一试{
entityManager=entityManagerFactory.createEntityManager();
Query Query=entityManager.createNativeQuery(sqlQuery);
query.setParameter(“cartId”,cartId);
List resultList=query.getResultList();
返回结果列表;
}最后{
如果(null!=entityManager){entityManager.close();}
}
观察结果
- 应用程序重新启动后,池利用率将降至最低,直到池利用率突然上升并最终达到最大限制。这种情况持续1-2天
- 一旦池达到最大连接限制,与返回的连接计数相比,借用的连接计数将以更快的速度增加,否则返回的连接计数将彼此非常接近
- 同时,放弃的连接计数也开始随着放弃日志的增加而增加
- 有趣的是,池耗尽后,查询响应时间保持不变。这样就排除了慢速查询
- 这个问题甚至发生在交通量最小的最奇怪的时刻。因此,它与交通无关
将返回并在任何情况下更新。自上次更新问题后: 在观察了相当长一段时间的性能之后,我们得出结论,在文件模式(嵌入式)中使用H2不知何故会定期导致文件锁定异常(尽管不规则) 由于我们的应用程序不需要在应用程序的生命周期之后保存数据,因此我们决定转向纯内存模式
尽管文件锁异常的神秘性还需要揭示。您使用的是哪个H2 jdbc驱动程序版本;这是最新的吗?我们使用的是1.4.196。1.4.197是截至2018年3月的最新版本。@MickMnemonic,我似乎找不到最新版本的发行说明,所以不知道版本升级是否能解决问题。@manu列出了1.4.196的250个错误修复!因此,如果升级对您来说是可行的,那么升级似乎是值得的,即使它不一定能解决您的特定问题。感谢@skomisa提供的发行说明。我在看他们的Github回购协议。我肯定能做到。