Блокируются ли строки по порядку в операторе SELECT ORDER BY FOR UPDATE?

Этот вопрос можно рассматривать как продолжение моего комментария к Могут ли два одновременных, но идентичных оператора DELETE вызвать взаимоблокировку?.

Мне интересно, заблокированы ли строки в порядке возрастания my_status в следующем выражении:

SELECT 1 FROM my_table ORDER BY my_status FOR UPDATE;

На https://www.postgresql.org/docs/9.5/static/sql-select.html, в котором говорится:

Команда SELECT может выполняться на уровне изоляции транзакций READ COMMITTED и использовать ORDER BY и предложение блокировки, чтобы возвращать строки не по порядку. Это потому, что ORDER BY применяется первым. Команда сортирует результат, но затем может заблокировать попытку получить блокировку одной или нескольких строк. Как только SELECT разблокируется, некоторые значения упорядоченных столбцов могут быть изменены, что приведет к тому, что эти строки будут выглядеть не по порядку (хотя они упорядочены с точки зрения исходных значений столбцов). При необходимости это можно обойти, поместив предложение FOR UPDATE/SHARE в подзапрос, например

SELECT * FROM (SELECT * FROM mytable FOR UPDATE) ss ORDER BY column1;

Я не уверен, что это отвечает на мой вопрос. Все это говорит о том, что ORDER BY применяется первым и что вам нужно поместить FOR UPDATE в подзапрос, чтобы обойти побочный эффект, заключающийся в том, что фактический порядок вывода может отличаться, если значения столбцов порядка были изменены в то же время. Другими словами, размещение FOR UPDATE в подзапросе гарантирует, что блокировка произойдет до упорядочения.

Но на самом деле это не говорит нам, действительно ли строки заблокированы в порядке, определяемом предложением ORDER BY?


person Community    schedule 22.08.2018    source источник


Ответы (1)


Строки заблокированы в порядке предложения ORDER BY, как это было при сканировании таблицы.

Запрос выполняется и строки упорядочиваются, затем PostgreSQL блокирует строки по порядку. По сути, ORDER BY происходит до FOR UPDATE.

Теперь может случиться так, что блокировка строки заблокируется из-за блокировок, удерживаемых параллельными транзакциями. Если это произойдет, и мы находимся на уровне изоляции READ COMMITTED, PostgreSQL ждет, пока не сможет получить блокировку, и затем извлекает текущую версию строки, которую он блокирует.

Если параллельная транзакция изменила столбцы, определяющие порядок, окончательный результат не будет в порядке, определенном параметром ORDER BY.

person Laurenz Albe    schedule 23.08.2018