【问题标题】:If a @Transactional annotated method is called from another @Transactional annotated method, does this result in two connections being consumed?如果从另一个@Transactional 注释方法调用@Transactional 注释方法,这是否会导致消耗两个连接?
【发布时间】:2021-01-01 15:30:46
【问题描述】:

迟到了,我们已经多次让 hikari 连接池耗尽。抛出的异常如下:

"org.springframework.transaction.CannotCreateTransactionException: 
Could not open JDBC Connection for transaction;
nested exception is java.sql.SQLTransientConnectionException: 
HikariPool-1 - Connection is not available, request timed out after 30000ms."

我观察到一些不知情的开发人员在数据库 (Postgres) 上的许多简单 get 调用中添加了 @Transactional 注释。

我们使用JdbcTemplate 进行数据库调用,默认连接池大小为 10。

控制器上的公共端点已经注释为@Transactional。当调用DAO层的单独bean的服务层已经是@Transactional时,是否可以在DAO Beans中添加@Transactional注解导致嵌套连接的创建。

我们还有一些预定的 CRON 作业,我看到这些作业没有通过公共 api 公开或通过控制器公开,但我是否仍需要在此类 cron/internal 的父级方法中添加 @Transactional能够以最佳方式进行数据库调用的方法?我们预计这些 cron 作业的更改不会回滚。我们已经使用了JdbcTemplate,它使用了 Hikari Connection poo。 @Transactional 在这种情况下是否需要优化性能。

所有配置都是默认的 spring boot 配置,所以默认的 Tx.Type 是 REQUIRED 除非明确设置。

【问题讨论】:

  • 将您的配置添加到问题中,当您的系统具有高流量或特定请求时也会发生这种情况吗?是否添加了 hikari 泄漏检测属性?
  • 是的,我们添加了泄漏检测,除了spring默认没有配置。
  • 也许你已经过度使用 @Transactional 即使在不使用数据库的时候,例如在验证错误的情况下
  • 你是否使用额外的连接池作为 PGBouncer?
  • 对于创建 Web 层的初学者来说,事务边界通常不是一个好主意,因为服务层应该是事务边界。在网络上,您的 tx 保持活动的时间过长,因此连接保持打开的时间比需要的时间长。不管事情不会被回滚,它们可能每次您进行数据访问时都需要一个事务,除了 java/spring 中的安全性之外,这还允许优化资源使用。并确保您没有直接对连接进行操作,除非您同时关闭它们!

标签: postgresql spring-boot spring-transactions jta hikaricp


【解决方案1】:

@Transactional应该主要用在即将使用数据库连接的服务层,应该用在代表业务流的最小方法上。

我认为您过度使用它并且可能会创建不必要的连接,从而在重载池上创建超时

请注意,您仅使用 one database connection pool,作为 HikariCP,而不是例如 PGBouncer。

还可以在 wiki page 中查看 HikariCP 的更多性能/配置调整

【讨论】:

    猜你喜欢
    • 2018-02-23
    • 2011-09-07
    • 2015-05-27
    • 2020-03-29
    • 2021-04-25
    • 2012-08-25
    • 2019-11-18
    • 2020-02-14
    相关资源
    最近更新 更多