Estou tendo problemas de simultaneidade com minhas inserções em um procedimento armazenado. A parte relevante do procedimento é esta:
select @_id = Id from table1 where othervalue = @_othervalue
IF( @_id IS NULL)
BEGIN
insert into table1 (othervalue) values (@_othervalue)
select @_id = Id from table1 where othervalue = @_othervalue
END
Quando executamos 3 ou 4 desses procs armazenados simultaneamente, obtemos várias inserções de vez em quando.
Estou pensando em corrigir isso assim:
insert into table1 (othervalue)
select TOP(1) @_othervalue as othervalue from table1 WITH(UPDLOCK)
where NOT EXISTS ( select * from table1 where othervalue = @_othervalue )
select @_id = Id from table1 where othervalue = @_othervalue
A questão é: é assim que inserir simultaneamente sem duplicatas no sql server? O fato de eu ter que usar o TOP para inserir apenas uma vez me perturba.
Respostas:
Você pode usar uma instrução de mesclagem com
serializable
dica.fonte
insert ... where not exist ...
padrão e constatei que você pode obter conflitos e violações de teclas; portanto, era necessário usar o updlock e o serializável. Depois, testei a declaração de mesclagem e pensei que ela lidaria com as coisas um pouco melhor e funcionou porque não havia impasses, mas eu ainda precisava usar serializável para não ter violações de chave.Se você não deseja duplicatas na coluna 'othervalue', pode fazê-lo criando uma
unique constraint
nessa coluna. A consulta seria:Isso retornaria um erro se uma consulta tentasse inserir um valor duplicado na coluna 'othervalue'.
fonte
Use uma restrição exclusiva, como a @StanleyJohns recomenda. Em seguida, use BEGIN TRY END TRY ao redor da instrução de inserção.
fonte