New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Transaction isolation level not working with R2dbcTransactionManager #30508
Comments
After deeper investigation, I believe the problem is following: In @Override
protected Mono<Void> doBegin(TransactionSynchronizationManager synchronizationManager, Object transaction,
TransactionDefinition definition) throws TransactionException {
....
return connectionMono.flatMap(con -> switchAutoCommitIfNecessary(con, transaction)
.then(Mono.from(doBegin(definition, con)))
.then(prepareTransactionalConnection(con, definition))
.doOnSuccess(v -> {
txObject.getConnectionHolder().setTransactionActive(true);
Duration timeout = determineTimeout(definition);
if (!timeout.isNegative() && !timeout.isZero()) {
txObject.getConnectionHolder().setTimeoutInMillis(timeout.toMillis());
}
// Bind the connection holder to the thread.
if (txObject.isNewConnectionHolder()) {
synchronizationManager.bindResource(obtainConnectionFactory(), txObject.getConnectionHolder());
}
}).thenReturn(con).onErrorResume(e -> {
if (txObject.isNewConnectionHolder()) {
return ConnectionFactoryUtils.releaseConnection(con, obtainConnectionFactory())
.doOnTerminate(() -> txObject.setConnectionHolder(null, false))
.then(Mono.error(e));
}
return Mono.error(e);
})).onErrorResume(e -> {
CannotCreateTransactionException ex = new CannotCreateTransactionException(
"Could not open R2DBC Connection for transaction", e);
return Mono.error(ex);
});
I believe that calling setAutoCommit is not necessary any more, because based on Connection interface autoCommit is disabled by beginTransaction(definition) method.: /**
* Begins a new transaction. Calling this method disables {@link #isAutoCommit() auto-commit} mode. Beginning the transaction may fail if the {@link TransactionDefinition} conflicts with the
* connection configuration.
*
* @param definition attributes for the transaction.
* @return a {@link Publisher} that indicates that the transaction is open
* @since 0.9
*/
Publisher<Void> beginTransaction(TransactionDefinition definition); To prove my theory, I have created wrapper around ConnectionFactory and basically ignore setAutoCommit call: @Component
@Aspect
public class FactoryWrapper {
@Around("execution(* io.r2dbc.spi.ConnectionFactory.create())")
public Object wrapConnection(ProceedingJoinPoint pjp) throws Throwable {
Publisher<? extends Connection> publisher = (Publisher<? extends Connection>)pjp.proceed();
return Mono.from(publisher)
.map(GuardAutoCommit::new);
}
private static class GuardAutoCommit implements Connection, Wrapped<Connection> {
private final Connection delegate;
private GuardAutoCommit(Connection delegate) {
this.delegate = delegate;
}
@Override
public boolean isAutoCommit() {
return delegate.isAutoCommit();
}
@Override
public Publisher<Void> setAutoCommit(boolean autoCommit) {
return Mono.empty();
}
....
@Override
public Connection unwrap() {
return delegate;
}
}
} and with that, it works. |
Thanks for the report! We seem to have missed the implicit auto-commit handling in R2DBC 0.9/1.0 when doing the upgrade. @mp911de I hope my corresponding changes make sense there. Since there is only cleanup step left, I've folded that logging/completion code into the release connection step itself. |
Spring boot: 3.1.0 and 3.1.1 (SNAPSHOT)
Database: PostgreSQL
Expected is something like (works in spring-boot 2.4.13):
I also investigated traffic with wireshark between PostgreSQL and my demo project, there is no isolation level information being set.
The text was updated successfully, but these errors were encountered: