У меня всегда был запрос в виде:
UPDATE
users
SET
col = 1
WHERE
user_id IN (
SELECT
user_id
FROM
users
WHERE
...
LIMIT 1
FOR UPDATE
);
И я был почти уверен, что он генерирует блокировку для затронутой строки до тех пор, пока обновление не будет выполнено.
Теперь я написал тот же запрос, используя CTE и выполнив
WITH query AS (
select
user_id
FROM
users
WHERE
...
LIMIT 1
FOR UPDATE
)
UPDATE
users
SET
col = 1
WHERE
user_id IN (
SELECT
user_id
FROM
query
);
У меня действительно есть некоторые сомнения, что он применяет блокировку строки из-за полученных результатов, но я не смог найти ничего задокументированного по этому поводу.
Может кто-нибудь прояснить? Спасибо
Редактировать:
Мне удалось найти это:
Если указанные c таблицы названы в FOR UPDATE или FOR SHARE, то только строки из этих таблиц заблокирован; любые другие таблицы, используемые в SELECT, просто читаются как обычно. Предложение FOR UPDATE или FOR SHARE без списка таблиц влияет на все таблицы, используемые в операторе. Если для представления или подзапроса применяется FOR UPDATE или FOR SHARE, это влияет на все таблицы, используемые в представлении или подзапросе. Однако FOR UPDATE / FOR SHARE не применяются к запросам WITH, на которые ссылается основной запрос. Если вы хотите, чтобы в запросе WITH происходила блокировка строки, укажите FOR UPDATE или FOR SHARE в запросе WITH.
https://www.postgresql.org/docs/9.0/sql-select.html#SQL -FOR-UPDATE-SHARE
Поэтому я думаю, что это должно работать, только если for for находится в запросе with, а не в запросе, использующем with?