LINUX.ORG.RU

unique constraint violations

 


0

1

может кому-то поможет такой хитрый ход потому как я именно такого решения не нашел.

положим нужно заинсертить в таблицу уникальных ключей заранее известный ключ, но мы не знаем есть он или нет и соответственно хотим исключить ошибку и ситуацию гонки. положим ключ равен 777.

CREATE TABLE x(id BIGINT, PRIMARY KEY(id));

BEGIN;
SELECT pg_advisory_xact_lock(777);
INSERT INTO x (id) SELECT 777 WHERE NOT EXISTS (SELECT id FROM x WHERE id=777) RETURNING id;
COMMIT;

pg_advisory_xact_lock исключает ситуацию гонки залочиваясь и ожидая commit/rollback параллельной транзации или обрыва паралелльного соединения с базой.

insert добавляет запись только если ее еще нет, и по возвращенному им значению понятно было это добавление или нет

★★★★

В принципе можно и без лока, если упадёт на вставке, то просто повторить транзакцию. Собственно это пример пессимистичных и оптимистичных блокировок. Оба варианта имеют право на существование.

anonymous
()

Адвайзори локи (собственно как и любые другие) плохо масштабируются. Хотя ими легко огораживать юзерспецифик действия, чтобы не париться с ловлей IntegrityError.

bj
()

а лор-то еще не скатился.

anonymous
()

О какой гонке идёт речь? Транзакции гарантируют атомарность и параллельность, разве нет? Достаточно выставить нужный уровень изоляции и всё.

Legioner ★★★★★
()
Ответ на: комментарий от Legioner

даже если это так для BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE (в чем я для INSERT не уверен) - то все равно явно гораздо дешевле разруливать этим локом конкретные совпадения ключей чем выстраивать в очередь все подобные транзакции

quest ★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.