Я пытаюсь понять, как уровни изоляции READ COMMITED и READ UNCOMMITED работают в Hibernate, и мне нужно какое-то объяснение.
Есть 2 потока THR1 и THR2, которые выполняют один и тот же метод транзакции (Spring аннотация Transactional с уровнем изоляции READ COMMITED). Назовите транзакции, созданные этими потоками, TRA1 и TRA2 соответственно. Транзакционный метод выглядит следующим образом:
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
}
}
Класс Preference аннотируется Entity (optimisticLock = OptimisticLockType.NONE), чтобы применить модель 2PL для этого объекта (я ошибаюсь?). Я использую базу данных Oracle.
Рассмотрим следующие сценарии:
Предположим, что поток THR1 переходит к строке 1 и запрашивает объект. Если я правильно понимаю, транзакция TRA1, созданная этим потоком, получает общую блокировку чтения для запрашиваемого объекта. Затем, если поток THR2 переходит к строке 3, пытаясь получить исключительную блокировку записи для этого объекта, не следует ли блокировать THR2 до тех пор, пока TRA1 не освободит блокировку чтения?
Предположим, что поток THR1 переходит к строке 3 и получает эксклюзивную блокировку записи для объекта (эксклюзивная блокировка сохраняется до тех пор, пока TRA1 транзакция завершена). Затем поток THR2 переходит к строке 1 и пытается запросить этот объект. Не следует ли блокировать THR2, потому что транзакция TRA2 пытается получить блокировку чтения, в то время как другая транзакция TRA1 удерживает исключительную блокировку записи для этого объекта?
Если я воспроизведу сценарий из пункта 2 для уровня изоляции READ UNCOMMITED, THR2, выполняющий транзакцию TRA2, не увидит изменений, внесенных THR1 в транзакции TRA1 даже после обновление или запрос объекта снова ("оценить выражение" при отладке). Почему?