I try to understand the way READ COMMITED and READ UNCOMMITED isolation levels works in Hibernate and need some explanation.
There are 2 threads THR1 and THR2 both executing the same transactional method (Spring Transactional annotation with isolation level set to READ COMMITED). Name transactions created be these threads TRA1 and TRA2 accordingly. The transactional method looks as follows:
public void updateOrSavePreference(String name, String value) {
Preference preferenceToUpdate = findPreferenceUsingNamedQuery(name); // line 1. shared read lock acquired (uses HibernateTemplate.findByNamedQueryAndNamedParam(...))
if (preferenceToUpdate != null) { // line 2.
preferenceToUpdate.setValue(value); // line 3. exclusive write lock acquired (actually I use the HibernateTemplate.merge(...) method
// instead a setter because the entity type is immutable, but it seems irrelevant for this example)
} else { // line 4.
HibernateTemplate.save(preferenceToUpdate); // line 5. exclusive write lock acquired
}
}
The Preference class is annotated with Entity(optimisticLock = OptimisticLockType.NONE) to enforce 2PL model for this entity (am I wrong?). I use Oracle database.
Consider following scenarios:
Let's assume that thread THR1 steps to line 1 and queries an object. If I understand correctly, the transaction TRA1 created by this thread acquires a shared read lock for the queried entiry. Then, if the THR2 thread steps to line 3 trying to acquire an exclusive write lock for this entity shouldn't THR2 be blocked until TRA1 releases the read lock?
Let's assume that thread THR1 steps to line 3 and acquires an exclusive write lock for an entity (exclusive lock is held until the TRA1 transaction completes). Then, the THR2 thread steps to line 1 and tries to query this entity. Shouldn't THR2 be blocked because the TRA2 transaction tries to acquire a read lock while other transaction TRA1 holds an exclusive write lock for this entity?
If I reproduce the scenario from point 2 for the READ UNCOMMITED isolation level, THR2 executing the TRA2 transaction doesn't see changes made by THR1 in the TRA1 transaction even after refreshing or querying the entity again ("evaluate expression" under debug). Why?