Correção de impasse do SQL Server:Forçar pedido de adesão ou tentar novamente automaticamente?
-
24-09-2019 - |
Pergunta
eu tenho um procedimento armazenado que executa uma junção de TableB
para TableA
:
SELECT <--- Nested <--- TableA
Loop <--
|
---TableB
Ao mesmo tempo, em uma transação, as linhas são inseridas em TableA
, e depois em TableB
.
Esta situação ocasionalmente causa conflitos, pois o procedimento armazenado select captura linhas de TabelaB, enquanto a inserção adiciona linhas a TabelaA, e então cada um quer que o outro solte a outra mesa:
INSERT SELECT
========= ========
Lock A Lock B
Insert A Select B
Want B Want A
....deadlock...
A lógica requer o INSERT
para primeiro adicionar linhas a A, e depois para B, embora eu pessoalmente não me importe com a ordem em que o SQL Server executa sua junção - contanto que ele se junte.
A recomendação comum para corrigir impasses é garantir que todos acessem os recursos na mesma ordem.Mas neste caso o otimizador do SQL Server está me dizendo que a ordem oposta é “melhor”.posso forçar outro pedido de associação e ter uma consulta com desempenho pior.
Mas eu deveria?
Devo substituir o otimizador, agora e para sempre, por uma ordem de associação que desejo usar?
Ou devo apenas capturar o erro erro nativo 1205, e reenviar a instrução select?
A questão não é quão pior o desempenho da consulta pode ser quando eu substituo o otimizador e ele faz algo não ideal.A questão é:é melhor tentar novamente automaticamente, em vez de executar consultas piores?
Solução
É melhor tentar novamente impulso de impulso automaticamente. A razão é que você pode consertar isto Deadlock, apenas para acertar outro depois. O comportamento pode mudar entre as liberações do SQL, se o tamanho das tabelas mudar, se as especificações do hardware do servidor mudarem e mesmo se a carga no servidor mudar. Se o impasse for frequente, você deve tomar medidas ativas para eliminá -lo (um índice geralmente é a resposta), mas para impasse raro (digamos a cada 10 minutos), tente novamente no aplicativo mascarar o impasse. Você pode tentar novamente leituras ou As gravações, uma vez que as gravações estão, obviamente, cercadas por transações iniciais/comprometidas adequadas para manter todas as operações de gravação atômicas e, portanto, capazes de tentar novamente sem problemas.
Outra avenida a considerar está ligando Leia o instantâneo comprometido. Quando isso estiver ativado, o Select simplesmente não pega bloqueios, mas produz leituras consistentes.
Outras dicas
É conhecido como coverflow no iOS.Siga Este link Você vai conseguir o que queria e virá a saber como implementá-lo./ p >.
ou você pode Consulte esta pergunta sobre o estouro de pilha também.
Trapping e reexecução podem funcionar, mas você tem certeza de que o SELECT é sempre a vítima do deadlock?Se a inserção for a vítima do impasse, você terá que ter muito mais cuidado ao tentar novamente.
A solução mais fácil neste caso, eu acho, é NOLOCK ou READUNCOMMITTED (mesma coisa) sua seleção.As pessoas têm preocupações justificáveis sobre leituras sujas, mas há anos executamos o NOLOCK em todos os lugares para obter maior simultaneidade e nunca tivemos problemas.
Eu também faria um pouco mais de pesquisa sobre semântica de bloqueio.Por exemplo, acredito que se você definir o nível de isolamento da transação como instantâneo (requer 2005 ou posterior), seus problemas desaparecerão.