create table a (
b text not null unique,
c text not null
);
-- Sleeps for 1 second as expected.
insert into a (b, c) values ('d', pg_sleep(1));
-- Sleeps for 1 second even though record is not inserted.
insert into a (b, c) values ('d', pg_sleep(1));
Existe alguma maneira de reestruturar a segunda instrução de modo que a pg_sleep
(ou a função intensiva real que estou chamando) seja executada apenas se nenhuma restrição for violada com base em b
? Observe que c
(o resultado da chamada de função) não tem influência na restrição.
Algumas soluções alternativas:
insert
com apenasb
eupdate
c
na próxima instrução seinsert
ocorreu sem erro. A desvantagem é que tenho que afrouxar/remover anot null
restrição dec
, pois ela será temporariamente nula.Sob um bloqueio consultivo, verifique se já existe um
a
with mesmob
e, se não, faça oinsert
. A desvantagem é que eu replico a verificação de exclusividade manualmente e tenho implicações negativas no desempenho.
Se você colocar o cheque na mesma consulta, a chamada de função cara só será executada se ainda não houver nenhuma linha conflitante:
Agora, a inserção ainda pode falhar sob carga de gravação simultânea. O Postgres não permite bloquear linhas hipotéticas. (Portanto, não vejo como um bloqueio de aconselhamento ajudaria.) Mas isso só acontece se uma transação simultânea inserir o mesmo valor simultaneamente
b
e for extremamente rara. Nesse caso, você só perde a otimização do desempenho e nada quebra.