Postgres INSERT DO UPDATE проблема параллелизма - PullRequest
0 голосов
/ 05 декабря 2018

Предположим, у меня есть простая таблица names:

CREATE TABLE names(
    id SERIAL PRIMARY KEY,
    name TEXT,
    CONSTRAINT names_name_key UNIQUE (name)
);

У меня есть следующий запрос, который я выполняю в нескольких потоках:

WITH ins AS (
   INSERT INTO names(name)
   VALUES ('bob')
   ON     CONFLICT ON CONSTRAINT names_name_key DO UPDATE
   SET    name = NULL
   WHERE  FALSE      -- never executed, but locks the row
   RETURNING id
   )
SELECT id FROM ins
UNION  ALL
SELECT id FROM names
WHERE  name = 'bob'  -- only executed if no INSERT
LIMIT  1;

Возможно ли это когда-либо для этогозапрос не дал результатов?Я понимаю, что запрос будет блокироваться до тех пор, пока другие транзакции, выполняющие эту фиксацию или откат запроса, не будут ли подтверждены последующим оператором SELECT, чтобы увидеть эту зафиксированную транзакцию?

Примеры были скопированы из этойSO thread: Возвращает строки из INSERT с ON CONFLICT без необходимости обновления

Обновление: Ответ на самом деле - да.Откройте два сеанса Postgres и выполните запрос в следующем порядке:

Поток A

BEGIN;
execute query;

Поток B

BEGIN; 
execute query; 

Обратите внимание: B заблокирован и ожидает A для фиксации или отката.

Нить A

COMMIT;

Нить B разблокируется, а затем не возвращает результатов.

...