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?

Foi útil?

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.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top