【发布时间】: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