Eu acho que você está tentando resolver o problema de maneira incorreta. O que você deseja é a máxima proteção da consistência do banco de dados. Se duas pessoas executam um procedimento armazenado ao mesmo tempo, a consistência do banco de dados pode ser violada.
Para proteger contra vários tipos de inconsistências do banco de dados, o padrão SQL possui quatro níveis de isolamento de transação:
- LEIA NÃO COMPROMETIDO onde basicamente as transações perdem seu valor, outras transações veem dados sujos. Não use isso!
- LEIA COMPROMETIDO onde as transações veem apenas dados confirmados, mas pode haver inconsistências nas quais duas transações podem passar por cima dos dedos uma da outra
- LEITURA REPETIDA, onde é resolvido um tipo de inconsistência, leitura não repetível
- SERIALIZABLE, que garante que exista alguma ordem virtual na qual a execução das transações levaria aos resultados que sua execução resultou em
No entanto, o padrão SQL possui uma abordagem baseada em bloqueio para essas inconsistências do banco de dados e, por razões de desempenho, muitos bancos de dados adotam uma abordagem baseada em isolamento de instantâneo que basicamente possui esses níveis:
- LEIA COMPROMISSO, que é o mesmo em bancos de dados com bloqueio
- SNAPSHOT ISOLATION em que o banco de dados vê uma captura instantânea de todos os dados e se tenta atualizar uma linha que foi atualizada por alguma outra transação, é cancelada, mas existem algumas anomalias conhecidas que podem ocorrer
- SERIALIZABLE, que é o mesmo dos bancos de dados baseados em bloqueio, mas desta vez implementado de maneira diferente, não bloqueando, mas garantindo que não haja violações de serialização e, se essa violação for detectada, cancelando uma transação
Os cancelamentos de transação nesses bancos de dados baseados em isolamento de captura instantânea podem parecer preocupantes, mas, novamente, todos os bancos de dados cancelam uma transação devido a um conflito, portanto, qualquer aplicativo razoável precisa, de qualquer maneira, poder tentar novamente uma transação.
O que você deseja é o nível de isolamento SERIALIZABLE : garante que se as transações executadas independentemente uma após a outra resultem em um bom estado, qualquer execução paralela das transações também resultará em um bom estado. Felizmente, Michael Cahill, em sua tese de doutorado, descobriu como o nível de isolamento SERIALIZABLE pode ser suportado por bancos de dados isolados de captura instantânea com pouco esforço.
Se estiver usando um nível de isolamento SERIALIZABLE em um banco de dados isolado de captura instantânea, se duas pessoas tentarem executar o procedimento armazenado simultaneamente e pisarem nos dedos uma da outra, uma das transações será cancelada.
Agora, o SQL Server oferece suporte genuíno ao nível de isolamento SERIALIZABLE (em vez de mascarar o isolamento de instantâneo atrás da palavra-chave SERIALIZABLE )? Francamente, não sei: o único banco de dados que conheço que o suporta é o PostgreSQL.
Mesmo que eu não tenha dado conselhos específicos ao SQL Server, continuo postando essa resposta, pois usuários do PostgreSQL e usuários de outros bancos de dados que podem considerar a possibilidade de mudar para o PostgreSQL podem se beneficiar da minha resposta. Além disso, os usuários de bancos de dados não PostgreSQL que não podem mudar para o PostgreSQL podem pressionar seu fornecedor de banco de dados favorito para oferecer um nível de isolamento SERIALIZABLE genuíno .