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