помешало вставить.
Делаю так:
WITH ins AS (
INSERT INTO storage (key, value)
VALUES ($1, $2)
ON CONFLICT (key) DO NOTHING
RETURNING key, value
)
(SELECT key, value FROM ins)
UNION ALL
(SELECT key, value FROM storage WHERE key = $1)
LIMIT 1
Вопрос: сработает ли это при одновременной вставке, когда строки с ключем еще нет? Мне кажется, да.
Рассуждаю так: второй параллельный INSERT залочится ожидая завершения первой транзакции, после чего случится ON CONFLICT DO NOTHING и оно перейдет во вторую часть UNION ALL где из-за READ COMMITTED изоляции уже должна быть видна только что вставленная строка.
Я прав?
Немного разверну мысль. В целом каждый statement в транзакции видит свой снапшот. При Read Comitted разные statement могут увидеть разное состояние базы. Но вот может ли поменяться снэпшот внутри одного выражения? Цитата из доки: > It is very difficult to enforce business rules regarding data integrity using Read Committed transactions because the view of the data is shifting with each statement, and even a single statement may not restrict itself to the statement's snapshot if a write conflict occurs. т.е. если был write conflict , то вроде как может, а значит должно сработать.
Обсуждают сегодня