Description
Valentin Kovalenko opened SPR-16463 and commented
Let's imagine two bean methods:
@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.READ_UNCOMMITTED)
public void methodA(Runnable action) {
jdbc.execute("select 'inside methodA before methodB'");
action.run();
jdbc.execute("select 'inside methodA after methodB'");
}
@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.SERIALIZABLE)
public void methodB() {
jdbc.execute("select 'inside methodB'");
}
and we want to use them like this:
public void use() {
bean.methodA(bean::methodB);
}
This is a tricky case: it can't be implemented without violating the semantics of either Transactional.propagation
or Transactional.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 situation bean.methodA(bean::methodB)
in his project. Thus the user may believe that methodB
is always executed in a transaction context with Isolation.SERIALIZABLE
, which does not happen to be true.
The same is true not only for Propagation.REQUIRED
, but also for Propagation.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 with Isolation.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
or Transactional.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:
- Add warning and/or exception facility to propagating transactions that try to change the isolation level [SPR-4192] #8870 Add warning and/or exception facility to propagating transactions that try to change the isolation level
Referenced from: commits cc77b4b, 0ac117f, f789895
Backported to: 4.3.15