Могут ли два оператора "ВЫБЕРИТЬ ДЛЯ ОБНОВЛЕНИЯ" в одной таблице вызвать тупик?
Предположим, что две одновременные транзакции выполняют следующие запросы в DB Postgresql:
Транзакция A:
SELECT * FROM mytable WHERE id IN (1, 2, 3, 4) FOR UPDATE
Транзакция B:
SELECT * FROM mytable WHERE id IN (6, 3, 2, 1) FOR UPDATE
Возможно ли возникновение тупика из-за того, что Postgresql приобретает блокировки строк в непоследовательном порядке? Например. если Postgresql должен был получить блокировки строк в порядке, указанном в этом примере, тогда существует вероятность тупика.
Или Postgresql достаточно внутренне достаточно интеллектуальный, чтобы всегда получать блокировки строк таким образом, что одновременные, дискретные операторы SELECT FOR UPDATE
в одной и той же таблице не могут блокировать друг друга (например, всегда приобретая блокировки строк в порядке первичного ключа)?
Если Postgresql автоматически не предотвращает появление таких взаимоблокировок, существует ли способ изменить запросы для предотвращения такой ситуации (например, если на самом деле Postgresql получает блокировки строк в порядке, указанном идентификаторами, а затем последовательно сортирует идентификаторы должен предотвратить тупик)?
Спасибо за любую помощь!
Ответы
Ответ 1
Извините, у меня был еще один ответ, но это было неправильно.
В документации указано, что предложение ORDER BY применяется перед предложением FOR UPDATE. Таким образом, блокировки приобретаются в любом порядке, в котором выбраны строки (я подтвердил как таковой путем тестирования). Если вам нужно выбрать их в другом порядке, вы можете использовать:
SELECT * FROM (SELECT * FROM table ORDER BY id FOR UPDATE) ORDER BY another_column;
Вы можете попробовать свой вопрос в списке рассылки PostgreSQL .
Ответ 2
Из http://www.postgresql.org/docs/9.1/static/explicit-locking.html:
PostgreSQL автоматически определяет ситуации взаимоблокировки и разрешает их, прерывая одну из транзакций
Эта страница использует пример с UPDATE
s, который эквивалентен SELECT ... FOR UPDATE
относительно блокировки.