在 OutOfMemoryError 后恢复 Hikaricp
Recover Hikaricp after OutOfMemoryError
我有一个非常具体的场景,在执行查询期间,特别是在从数据库中获取行到我的结果集期间,我得到一个 OutOfMemoryError。
代码很简单:
public interface MyRepository extends Repository<MyEntity, Long> {
@EntityGraph(value = "MyBigEntityGraphToFetchAllCollections", type = EntityGraphType.FETCH)
@QueryHints({@QueryHint(name = "org.hibernate.readOnly", value = "true")})
MyEntity getOneById(Long id);
}
public class MyService {
...
public void someMethodCalledInLoop(Long id) {
try{
return repository.getOneById(id);
} catch (OutOfMemoryError error) {
// Here the connection is closed. How to reset Hikaricp?
System.gc();
return null;
}
}
}
似乎很奇怪 getOne 会占用所有内存,但由于急于获取大约 80 个集合以及行的倍增,某些情况下是无法支持的。
我知道我可以选择延迟加载集合,但我不想这样做。在每次加载时访问数据库 1+N 次会消耗更多时间,而我的应用程序没有。它是对数百万条记录的批处理,不到 0.001% 会对内存产生这种影响。所以我的策略是丢弃这几条记录并处理下一条。
捕获 OutOfMemoryError
后内存被释放,故障实体变成垃圾。但是由于这个错误,HikariCP 关闭(或被迫)连接。
在接下来的方法调用中,hikaricp 仍然给我关闭连接。似乎由于内存不足,hikaricp 没有正确完成之前的事务并永远停留在这种状态。
我现在的意图是重置或恢复 hikaricp。我不需要关心使用池的其他线程。
所以,毕竟,我的简单问题是,如何在不重启应用程序的情况下以编程方式重启或恢复 hikarycp 到其主要状态。
非常感谢阅读本文的人。
尝试将此添加到您的 Hibernate 配置中:
<property name="hibernate.hikari.connectionTestQuery">select 1</property>
这样 HikariCP 将在将连接提供给 Hibernate 之前测试连接是否仍然存在。
到目前为止没有任何效果。
我通过在方法中添加 'query hint' 来最小化问题:
@QueryHints({@QueryHint(name = "org.hibernate.timeout", value = "10")})
MyEntity getOneById(Long id);
99% 的结果集在 1 秒或更短的时间内获取,但有时结果集太大,需要更长的时间。这样 JDBC 在内存受到损害之前停止获取结果。
我有一个非常具体的场景,在执行查询期间,特别是在从数据库中获取行到我的结果集期间,我得到一个 OutOfMemoryError。
代码很简单:
public interface MyRepository extends Repository<MyEntity, Long> {
@EntityGraph(value = "MyBigEntityGraphToFetchAllCollections", type = EntityGraphType.FETCH)
@QueryHints({@QueryHint(name = "org.hibernate.readOnly", value = "true")})
MyEntity getOneById(Long id);
}
public class MyService {
...
public void someMethodCalledInLoop(Long id) {
try{
return repository.getOneById(id);
} catch (OutOfMemoryError error) {
// Here the connection is closed. How to reset Hikaricp?
System.gc();
return null;
}
}
}
似乎很奇怪 getOne 会占用所有内存,但由于急于获取大约 80 个集合以及行的倍增,某些情况下是无法支持的。
我知道我可以选择延迟加载集合,但我不想这样做。在每次加载时访问数据库 1+N 次会消耗更多时间,而我的应用程序没有。它是对数百万条记录的批处理,不到 0.001% 会对内存产生这种影响。所以我的策略是丢弃这几条记录并处理下一条。
捕获 OutOfMemoryError
后内存被释放,故障实体变成垃圾。但是由于这个错误,HikariCP 关闭(或被迫)连接。
在接下来的方法调用中,hikaricp 仍然给我关闭连接。似乎由于内存不足,hikaricp 没有正确完成之前的事务并永远停留在这种状态。
我现在的意图是重置或恢复 hikaricp。我不需要关心使用池的其他线程。
所以,毕竟,我的简单问题是,如何在不重启应用程序的情况下以编程方式重启或恢复 hikarycp 到其主要状态。
非常感谢阅读本文的人。
尝试将此添加到您的 Hibernate 配置中:
<property name="hibernate.hikari.connectionTestQuery">select 1</property>
这样 HikariCP 将在将连接提供给 Hibernate 之前测试连接是否仍然存在。
到目前为止没有任何效果。
我通过在方法中添加 'query hint' 来最小化问题:
@QueryHints({@QueryHint(name = "org.hibernate.timeout", value = "10")})
MyEntity getOneById(Long id);
99% 的结果集在 1 秒或更短的时间内获取,但有时结果集太大,需要更长的时间。这样 JDBC 在内存受到损害之前停止获取结果。