-
Notifications
You must be signed in to change notification settings - Fork 38.5k
Doc: @Transactional.isolation does not guarantee the specified isolation level [SPR-16463] #21008
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
Comments
Juergen Hoeller commented This is essentially by design: Just like a transaction timeout and the read-only flag, an isolation level is 'just' a characteristic to be honored for newly started transactions. For participating in an existing transaction, it is the responsibility of the caller to semantically align there, and Spring does not give any particular guarantees about the validity of the overall arrangement. Point taken that we could have clearer documentation notes about this; I'll repurpose this ticket for it. I'll specifically hint at the existing "validateExistingTransaction" flag on our transaction manager implementations which checks the isolation level and read-only status of an existing transaction before participating, as a kind of assertion in order to provide accidental mismatches. |
Valentin Kovalenko commented
|
Valentin Kovalenko commented
if (currentIsolationLevel == null || currentIsolationLevel != definition.getIsolationLevel()) {
Constants isoConstants = DefaultTransactionDefinition.constants;
throw new IllegalTransactionStateException("Participating transaction with definition [" +
definition + "] specifies isolation level which is incompatible with existing transaction: " +
(currentIsolationLevel != null ?
isoConstants.toCode(currentIsolationLevel, DefaultTransactionDefinition.PREFIX_ISOLATION) :
"(unknown)"));
} and hence throws org.springframework.transaction.IllegalTransactionStateException:
Participating transaction with definition [PROPAGATION_MANDATORY,ISOLATION_READ_UNCOMMITTED; 'rwTxManager',-java.lang.Throwable] specifies isolation level which is incompatible with existing transaction: ISOLATION_READ_COMMITTED while it is obviously perfectly fine to execute method requiring TRANSACTION_READ_UNCOMMITTED < TRANSACTION_READ_COMMITTED < TRANSACTION_REPEATABLE_READ < TRANSACTION_SERIALIZABLE |
Juergen Hoeller commented This was done on purpose back in #8870 (see the comments). The isolation level setting on a transaction definition is not a minimum isolation requirement, it is the actual isolation level desired. An inner transaction might not just be able to execute in |
Valentin Kovalenko commented
|
Valentin Kovalenko opened SPR-16463 and commented
Let's imagine two bean methods:
and we want to use them like this:
This is a tricky case: it can't be implemented without violating the semantics of either
Transactional.propagation
orTransactional.isolation
, because modern RDBMS do not allow changing an isolation level in the middle of a transaction, and Spring does not even try doing this. A user, however, may not realize this fact, or may not realize the fact that he actually has the situationbean.methodA(bean::methodB)
in his project. Thus the user may believe thatmethodB
is always executed in a transaction context withIsolation.SERIALIZABLE
, which does not happen to be true.The same is true not only for
Propagation.REQUIRED
, but also forPropagation.MANDATORY
. This means that annotating a method with@Transactional(propagation = Propagation.MANDATORY, isolation = Isolation.SERIALIZABLE)
does not guarantee that the method will be executed in a transaction context withIsolation.SERIALIZABLE
.I think that such behaviour violates the principle of least astonishment and may easily lead to bugs related to a usage of an incorrect isolation level. However, it may not be a good idea to always throw an exception when Spring cannot guarantee the demanded level of isolation. Possibly this can be solved by throwing an exception by default but providing a way to disable it by explicitly specifying which semantics the Spring framework should violate in such situations:
Transactional.propagation
orTransactional.isolation
. I believe the solution definitely requires discussing.The complete description of this situation can be found here: https://sites.google.com/site/aboutmale/techblog/transactionalcatch
Affects: 4.3.14
Issue Links:
Referenced from: commits cc77b4b, 0ac117f, f789895
Backported to: 4.3.15
The text was updated successfully, but these errors were encountered: