Skip to content

Connection leak when using r2dbc-pool & spring-tx #219

Description

@1528110566

Bug Report

Here is my demo. Update something that not exists, throw an exception in database transaction. Two statements executed parallel using Flux.

Query query = Query.query(Criteria.where("id").is(3));
Update update = Update.update("name", "3");
List<Integer> list = new ArrayList<>();
list.add(0);
list.add(1);
for (int i = 0; i < 1000; i++) {
    Flux.fromIterable(list)
            .flatMap(item -> {
                return transactionalOperator.transactional(template.update(query, update, User.class)
                        .doOnNext(res -> {
                            if (res != 1) {
                                throw new RuntimeException("test");
                            }
                        }));
            })
            .subscribe();
}

pool-max-size is 10.
After execution, actuator shows the number of idle connections is smaller than expected, which is 1.
image
image

However, when I move .doOnNext to another block, it works as expected (attention on ) behind User.class).

Query query = Query.query(Criteria.where("id").is(3));
Update update = Update.update("name", "3");
List<Integer> list = new ArrayList<>();
list.add(0);
list.add(1);
for (int i = 0; i < 1000; i++) {
    Flux.fromIterable(list)
            .flatMap(item -> {
                return transactionalOperator.transactional(template.update(query, update, User.class))
                        .doOnNext(res -> {
                            if (res != 1) {
                                throw new RuntimeException("test");
                            }
                        });
            })
            .subscribe();
}

Versions

Windows 11
JDK 1.8.0-381
Spring-parent 2.7.13
r2dbc-mysql 0.9.3
MySQL Server 9.1.0-1.el9

Steps to reproduce

https://github.com/1528110566/r2dbc-connection-leak-demo
This is a demo that can reproduce this bug.

  1. call http://localhost:8080/test
  2. wait background threads are finished
  3. call http://localhost:8080/actuator/prometheus
  4. search r2dbc_pool_acquired_connectionsand r2dbc_pool_idle_connections. We'll find the number of connection in the pool is not as expected. This can be proved with debugging on
    Mono<Connection> mono = this.connectionPool.acquire()

    We'will find the number of connection is actually smaller than expected.

Expected behavior/code

r2dbc_pool_acquired_connections is 0 and r2dbc_pool_idle_connections is 10 after execution.

Possible Solution

No idea.
I searched everywhere on GitHub, found lots of issues related to this problem.
I think this issue is very close to answer: pgjdbc/r2dbc-postgresql#661 , but it's too difficult to follow to me :(

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions