Skip to content

Connections are note released after nested transactions #314

Description

@cfeller-init

Hello,

I think there is a connection leak if you use nested transactions with a connection pool like Hikari. Here is a small example:

private final static String DATABASE_URL = "jdbc:h2:mem:account";

public static void main(String[] args) throws Exception {
    HikariConfig hikariConfig = new HikariConfig();
    hikariConfig.setJdbcUrl(DATABASE_URL);
    HikariDataSource hikariDataSource = new HikariDataSource(hikariConfig);
    try (ConnectionSource connectionSource = new DataSourceConnectionSource(hikariDataSource, DATABASE_URL)) {
        TransactionManager.callInTransaction(connectionSource, (Callable<Void>) () -> {
            System.out.println("outer start");
            TransactionManager.callInTransaction(connectionSource, (Callable<Void>) () -> {
                System.out.println("inner");
                return null;
            });
            System.out.println("outer end");
            return null;
        });
        System.out.format("Active connections : %d\n", hikariDataSource.getHikariPoolMXBean().getActiveConnections());
    }
}

At the end, I think, that active connections should be 0, but they are 1.

I think this is connected to this method in the TransactionManager:

public static <T> T callInTransaction(String tableName, final ConnectionSource connectionSource,
			final Callable<T> callable) throws SQLException {

	DatabaseConnection connection = connectionSource.getReadWriteConnection(tableName);
	boolean saved = false;
	try {
		saved = connectionSource.saveSpecialConnection(connection);
		return callInTransaction(connection, saved, connectionSource.getDatabaseType(), callable);
	} finally {
		// we should clear aggressively
		if (saved) {
			connectionSource.clearSpecialConnection(connection);
		}
		connectionSource.releaseConnection(connection);
	}
}

If we are in a nested context then saved is false (as we cannot save if we already have a special connection). saveSpecialConnection still increases the internal count in the NestedConnection in BaseConnectionSource. But we do not call clearSpecialConnection to lower that count.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions