Я использую Hibernate с Joined-SubClasses, чтобы сопоставить иерархию классов с
база данных. К сожалению, это вызывает взаимные блокировки, когда объект обновляется в то время как
другой поток пытается загрузить один и тот же объект. С объектами, которые отображаются
к одной таблице это не проблема. Кажется, это вызвано тем, как MSSQL
приобретает блокировки на таблицах иерархии классов.
Когда Hibernate загружает объект из базы данных, он использует SELECT с JOIN:
SELECT ...
FROM
subclass
LEFT JOIN class
ON ...
WHERE ...
Когда Hibernate обновляет объект этого подкласса, он делает:
UPDATE
class
SET ...
WHERE ...
UPDATE
subclass
SET ...
WHERE ...
Проблема в том, что если объект загружен между двумя операторами обновления, он
вызывает тупик. Оператор SELECT, кажется, блокирует 2 таблицы одну после
другой. Итак, что, кажется, происходит:
- Поток 1 загружает объект и устанавливает общие блокировки на обе таблицы
- Поток 1 выполняет инструкцию UPDATE для таблицы классов и обновляет
замок на столе класса для эксклюзивной блокировки.
- Поток 2 пытается загрузить тот же объект, выполнив инструкцию SELECT, он
помещает разделяемую блокировку в таблицу подклассов и затем ждет, пока эксклюзивный
блокировка на столе класса снята
- Поток 1 выполняет инструкцию UPDATE для таблицы подклассов, он хочет
обновить его блокировку на таблице подклассов до эксклюзивной блокировки, но
таблица уже заблокирована потоком 2, который ожидает поток 1
- Поток 2 прерван из-за тупика с потоком 1
График взаимоблокировки выглядит следующим образом: График взаимоблокировки
Эти объекты часто обновляются тихо, и это всегда вызывает взаимные блокировки
когда загружен только один объект. Я также пытался воспроизвести проблему с
HSQLDB, но тогда он не блокируется, HSQLDB, кажется, блокирует обе таблицы на
один раз или ждет, пока он не сможет заблокировать оба, так что кажется, что проблема только
происходит с MSSQL.
Каким было бы решение, чтобы избежать этой проблемы с Hibernate без изменения
схема (кроме индексов)?