在视图中禁用打开会话 vs handling_mode=DELAYED_ACQUISITION_AND_RELEASE_AFTER_STATEMENT

问题描述 投票:0回答:0

问题

我正在处理的大型单体 Spring Boot 应用程序存在“数据库连接”问题,所有这些都归结为应用程序未将数据库连接释放回池中的事实。

考虑以下场景:从控制器调用的服务方法:

void myMethod() {
  userRepository.findById(userId);
  thread.sleep(4000); // simulate remote method call
  userFriendsRepository.getFriendsByUserId(userId);
  thread.sleep(4000); // simulate remote method call
}

应用程序.properties

# Throw a warning when connection is not released
spring.datasource.hikari.leak-detection-threshold=3000

我们正在尝试评估潜在的解决方案:

潜在的解决方案

  1. 经过研究,这个问题有一个明显的解决方案是在视图模式中禁用打开会话(因为 Spring 在整个 http 请求期间保持休眠会话):

    spring.jpa.open-in-view = false
    

    在这种情况下,副作用与实体关系有关。

  2. 禁用自动提交并将休眠连接设置设置为在语句后释放:

    spring.datasource.hikari.auto-commit=false
    spring.jpa.properties.hibernate.connection.handling_mode=
    DELAYED_ACQUISITION_AND_RELEASE_AFTER_STATEMENT
    

    这种方法不太清楚。

问题:

我的主要问题:

  • 为什么使用方法 #2 警告

    Apparent connection leak detected
    仍然显示,即使属性说“声明后释放连接”。我的理解是,在此上下文中的“语句”是一个 SQL 查询,应该在方法
    userRepository.findById(userId);
    之后和
    thread.sleep(4000);
    甚至开始之前立即发布。请注意,这里我只考虑#2,“在视图中打开”仍然启用。

    有趣的观察:使用#2 并将

    thread.sleep
    减小到
    2000
    Apparent connection leak detected
    不再显示。即使两个超时加起来超过“泄漏阈值”。似乎连接是在执行下一个查询之前释放的,而不是在完成上一个查询之后立即释放的(即使打开了 open-session-in-view )。

  • 在#2 中,禁用自动提交会影响应用程序吗?我看到 Spring 已经在每个事务中禁用了自动提交:

    public class DataSourceTransactionManager {
       protected void doBegin(...) {
         ...
         con.setAutoCommit(false);
         ...
       }
    }
    

    According to this comment,它不应该,但我想知道为什么它在 Spring 默认情况下打开。是因为向后兼容吗?

  • 您在项目中遇到过类似的数据库连接问题吗?您是如何解决的?

我个人倾向于第 1 种方法,即禁用 open-session-in-view,但我想在做出决定之前了解这两种方法,以及它们将对现有应用程序产生哪些影响。

附言Vlad Mihalcea 有一篇关于这个主题的优秀文章,但它没有比较这两种方法并回答我的具体问题(或者我可能没有 100% 理解这篇文章)。

spring spring-boot hibernate spring-data-jpa hikaricp
© www.soinside.com 2019 - 2024. All rights reserved.