Подтвердить что ты не робот

Могут ли два оператора "ВЫБЕРИТЬ ДЛЯ ОБНОВЛЕНИЯ" в одной таблице вызвать тупик?

Предположим, что две одновременные транзакции выполняют следующие запросы в 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 получает блокировки строк в порядке, указанном идентификаторами, а затем последовательно сортирует идентификаторы должен предотвратить тупик)?

Спасибо за любую помощь!

4b9b3361

Ответ 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 относительно блокировки.