У нас есть приложение с простой таблицейPostgres 9.4 обнаруживает Тупик, когда чтение-модификация-запись на одной таблице
given_entity{
UUID id;
TimeStamp due_time;
TimeStamp process_time;
}
Это приложение весной загрузки (1.2.5.RELEASE), который использует весенне-данных- jpa.1.2.5.RELEASE с гибернацией 4.3.10.FINAL as jpa provier.
У нас есть 5 экземпляров этого приложения, каждый из которых имеет планировщик, работающий каждые две секунды и запрашивающий базу данных для строк, которые до сих пор не имеют обработанных должностей в течение последних 2 минут;
SELECT * FROM given_entity
WHERE process_time is null and due_time between now() and NOW() - INTERVAL '2 minutes'
FOR UPDATE
Требование: каждая строка таблицы выше успешно обрабатывается одним из экземпляров приложения. Затем экземпляр приложения обрабатывает эти строки и обновляет его поле process_time в одной транзакции. Это может занять не более 2 секунд, что является интервалом планировщика. Также у нас нет индекса, кроме индекса PK на этой таблице. Следует отметить, что эти экземпляры могут вставлять строки этой таблицы, которые вызывается отдельно клиентами.
Проблема: в журналах я вижу это сообщение от PostgreSQL (редко, но бывает)
ERROR: deadlock detected
Detail: Process 10625 waits for ShareLock on transaction 25382449; blocked by process 10012.
Process 10012 waits for ShareLock on transaction 25382448; blocked by process 12238.
Process 12238 waits for AccessExclusiveLock on tuple (1371,45) of relation 19118 of database 19113; blocked by process 10625.
Hint: See server log for query details.
Where: while locking tuple (1371,45) in relation "given_entity"
Вопрос: Как это происходит? Я проверил блокировки postgresql и обыскал интернет. Я не нашел ничего, что говорит о взаимоблокировке на одной простой таблице. Я также не смог воспроизвести эту ошибку с помощью теста.
Вы можете вставить код, в котором вы обновляете таблицу? ** select for update ** блокирует изменения другими транзакциями, нужно быть осторожным с ним. –
, чтобы избежать этих проблем в целом, вы можете использовать оптимизирующий механизм блокировки Hibernate (если только не существует действительно реальной причины блокировки записей, которые вы хотите обновить tio). Возможно, это также может быть полезно: http://blog.2ndquadrant.com/postgresql-anti-patterns-read-modify-write-cycles/ –
Для обновления мы просто обновляем поле process_time. Что-то вроде «UPDATE given_entity set process_time = now(), где id =? ' – Abareghi