1

I'm experiencing connection leaks with my spring data jdbc postgres app. Basically for my calls that are not called in a transaction the connection is acquired and released to the pool. However when it comes to transactional calls connections are not released and a connection leaks error comes up and points to the function that is annotated with @transactional. Also the most interesting thing is the pool statistics dont reflect this. they show all connections as idle even when there are unreleased connections.

@Configuration
@EnableJdbcRepositories("com.api.repositories")
public class DBConfig {
    
    @Autowired
    private DbProps dbProps;
    
    @Bean
    public DataSource readWriteDataSource() {
        LOGGER.info("DB Props: {}",dbProps.toString());
        PGSimpleDataSource dataSource = new PGSimpleDataSource();
        dataSource.setUrl(dbProps.getDbUrl());
        dataSource.setUser(dbProps.getDbUser());
        dataSource.setPassword(dbProps.getDbPassword());
        dataSource.setLogUnclosedConnections(true);
        return connectionPoolDataSource(dataSource);
    }

    protected HikariConfig hikariConfig(DataSource dataSource) {
        HikariConfig hikariConfig = new HikariConfig();
        int cpuCores = Runtime.getRuntime().availableProcessors();
        hikariConfig.setMaximumPoolSize(cpuCores*4);
        hikariConfig.setDataSource(dataSource);
        hikariConfig.setIdleTimeout(600000);
        hikariConfig.setLeakDetectionThreshold(30000);
        hikariConfig.setConnectionTimeout(30000);
        hikariConfig.setMaxLifetime(1800000);
        hikariConfig.setAutoCommit(false);
        return hikariConfig;
    }
 
    protected HikariDataSource connectionPoolDataSource(
            DataSource dataSource) {
        return new HikariDataSource(hikariConfig(dataSource));
    }

    @Bean
    public PlatformTransactionManager transactionManager(DataSource readWriteDataSource) {
        return new DataSourceTransactionManager(readWriteDataSource);
    }
    
    @Bean
    public NamedParameterJdbcOperations usersJdbcOperations(DataSource readWriteDataSource) {
      return new NamedParameterJdbcTemplate(readWriteDataSource);
    }

transaction functions

@Transactional(propagation = Propagation.REQUIRES_NEW, isolation = Isolation.REPEATABLE_READ, rollbackFor = Exception.class)
    public String placeBet(PlaceBet placebet) {
        try {
            Bet unsavedBet = Bet.builder().amount(BigDecimal.valueOf(placebet.amount()))
                    .coin(placebet.coin())
                    .game(placebet.game())
                    .gid(placebet.gid())
                    .uid(placebet.uid())
                    .name(placebet.name())
                    .created(LocalDateTime.now().truncatedTo(ChronoUnit.MILLIS))
                    .originalOdd(BigDecimal.valueOf(placebet.original_odd())).build();
            Bet savedBet = betRepository.save(unsavedBet);
            if (null != savedBet) {
                LOGGER.info("saved Bet: {}",savedBet.toString());
            }
            return "success";
        } catch (Exception e) {
            LOGGER.error("Error {} encountered saving bet: {} changes rolled Back",e.getMessage(),placebet.toString());
            return "bet error";
        }
    }

logs

2023-01-20 00:11:15 WARN  ProxyLeakTask.java:84 - Connection leak detection triggered for Pooled connection wrapping physical connection org.postgresql.jdbc.PgConnection@6fae4b49 on thread http-nio-8001-exec-11, stack trace follows
java.lang.Exception: Apparent connection leak detected
    at com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:100)
    at org.springframework.jdbc.datasource.DataSourceTransactionManager.doBegin(DataSourceTransactionManager.java:265)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.startTransaction(AbstractPlatformTransactionManager.java:400)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:373)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:595)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:382)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763)
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:708)
    at com.api.services.BetService$$EnhancerBySpringCGLIB$$23929008.placeBet(<generated>)
    at com.api.controllers.BetController.placeNewBet(BetController.java:132)
    at jdk.internal.reflect.GeneratedMethodAccessor89.invoke(Unknown Source)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:568)

pool stats

2023-01-20 00:11:58 DEBUG HikariPool.java:421 - HikariPool-1 - Pool stats (total=16, active=0, idle=16, waiting=0)
2023-01-20 00:11:58 DEBUG HikariPool.java:518 - HikariPool-1 - Fill pool skipped, pool is at sufficient level.

it is released some 30secs later yet the query took ms to complete what would be the issue?

2023-01-20 00:11:15 WARN  ProxyLeakTask.java:84 - Connection leak detection triggered for Pooled connection wrapping physical connection org.postgresql.jdbc.PgConnection@6fae4b49 on thread http-nio-8001-exec-11, stack trace follows
2023-01-20 00:11:56 DEBUG DataSourceTransactionManager.java:330 - Committing JDBC transaction on Connection [HikariProxyConnection@304420024 wrapping Pooled connection wrapping physical connection org.postgresql.jdbc.PgConnection@6fae4b49]
2023-01-20 00:11:56 DEBUG DataSourceUtils.java:242 - Resetting isolation level of JDBC Connection [HikariProxyConnection@304420024 wrapping Pooled connection wrapping physical connection org.postgresql.jdbc.PgConnection@6fae4b49] to 2
2023-01-20 00:11:56 DEBUG DataSourceTransactionManager.java:389 - Releasing JDBC Connection [HikariProxyConnection@304420024 wrapping Pooled connection wrapping physical connection org.postgresql.jdbc.PgConnection@6fae4b49] after transaction
2023-01-20 00:11:56 INFO  ProxyLeakTask.java:91 - Previously reported leaked connection Pooled connection wrapping physical connection org.postgresql.jdbc.PgConnection@6fae4b49 on thread http-nio-8001-exec-11 was returned to the pool (unleaked) 
martin kimani
  • 277
  • 8
  • 18
  • Is it actually leaking connections? Or do you just have some long running transactions? See https://stackoverflow.com/questions/54883940/apparent-connection-leak-detected-with-hikari-cp – Jens Schauder Jan 20 '23 at 09:02
  • its just one insert statement actually. the code is above there @JensSchauder and from my postgres logs the duration for those inserts is indicating less than 10ms as the duration – martin kimani Jan 20 '23 at 09:32
  • Do you get errors because you run out of connections? Do you get log messages indicating that the allegedly leaked connection was returned? Is your logger configured in a way that you would see these messages? – Jens Schauder Jan 20 '23 at 10:12
  • yes, when I call non transactional calls I can see the logs for returning the conns. for transactional I dont see them getting returned. – martin kimani Jan 20 '23 at 10:19
  • I'm talking about rows like this one `2019-02-26 11:25:35.024 INFO 924 --- [p-nio-80-exec-8] com.zaxxer.hikari.pool.ProxyLeakTask : Previously reported leaked connection com.mysql.jdbc.JDBC4Connection@ffd3737 on thread http-nio-80-exec-8 was returned to the pool (unleaked)` (from the referenced question) – Jens Schauder Jan 20 '23 at 10:31
  • @JensSchauder I have updated the logs for realising on the question as they wouldnt fit here. it is released like 30secs later. – martin kimani Jan 20 '23 at 12:40
  • So what it the thread in question doing during that time? – Jens Schauder Jan 20 '23 at 12:51
  • @martinkimani , do you have EnableTransactionManagement annotation somewhere? – Barracuda Jan 20 '23 at 12:52
  • @Barracuda no but I thought that is enabled by default in spring unless autoconfiguration is disabled? – martin kimani Jan 20 '23 at 13:11
  • @JensSchauder It's stuck I believe – martin kimani Jan 20 '23 at 13:12
  • Probably, but at which command? Use a debugger, to find the stacktrace it is stuck on. – Jens Schauder Jan 20 '23 at 13:18
  • According to this [answer](https://stackoverflow.com/questions/60424898/connection-leak-detected-by-hikaripool-leakdetectionthreshold) such warning doesn't mean you actually have a leak. I'd suggest to check **open-session-in-view** property and explicitly set it to false. ``` spring: jpa: open-in-view: false ``` Also could you provide a minimal reproducible example? – Ivan Vakhrushev Feb 05 '23 at 11:09

0 Answers0