Postgres: выберите для обновления с помощью CTE - PullRequest
2 голосов
/ 19 января 2020

У меня всегда был запрос в виде:

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?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...