Я заметил случайные тупики в журналах ошибок, причина в параллельном обновлении той же строки:
[1111]:LOG: process 1111 detected deadlock while waiting for ShareLock on transaction 123456789 after 1000.095 ms
[1111]:DETAIL: Process holding the lock: 2222. Wait queue: .
[1111]:CONTEXT: while locking tuple (9999999,99) in relation "ccc"
[1111]:STATEMENT: update ccc set modification_date_time=$1, ... where id=$7
[1111]:ERROR: deadlock detected
[1111]:DETAIL: Process 1111 waits for ShareLock on transaction 123456789; blocked by process 2222.
Process 2222 waits for AccessExclusiveLock on tuple (9999999,99) of relation 55555 of database 66666; blocked by process 1111.
Process 1111: update ccc set modification_date_time=$1, ... where id=$7
Process 2222: update ccc set modification_date_time=$1, ... where id=$7
[1111]:HINT: See server log for query details.
В приложении происходит следующее:
- Спящий режим загрузкисущность (строка)
- поле изменяется
- Hibernate сохраняет сущность в базе данных, в результате чего
UPDATE
оператор
Непонятно, почемуэто происходит, потому что это просто нормальное обновление, и процессы не должны зависеть друг от друга.Я понимаю, что это условие гонки, но с точки зрения приложения это не важно.
Я не до конца понимаю, что такое ShareLock
и AccessExclusiveLock
, поэтому у меня пока есть две идеи:
- При изменении объекта Hibernate / DB должен повысить уровень блокировки, и это не удается, поскольку другой поток уже имеет некоторую блокировку в этой строке.Решение - заблокировать рано?
- Иногда транзакции просто слишком медленные (> 1 с), и тупик дает ложное срабатывание.Решение - увеличить время ожидания?