A desconexão da rede interrompe uma consulta?

13

Recentemente, executei uma consulta de atualização em 100.000 registros. Percebi que havia cometido um erro enquanto a consulta estava sendo executada e rapidamente desconectei o cabo de rede.

A consulta de atualização

  1. parar o processamento e reverter completamente?
  2. continuar processando até a conclusão e confirmar?
  3. parar o processamento e deixar apenas parte das linhas de destino atualizadas?
robocop
fonte
2
depois que uma consulta atingir o servidor, ela continuará, a menos que você tenha cancelado a consulta no servidor.
JP Chauhan
1
O comentário de Martin fornece a resposta direta à sua pergunta, robocop. Se a rede notificar o SQL Server sobre a desconexão antes que sua consulta seja executada, o SQL Server o reverterá. Caso contrário, se a consulta for concluída antes que o SQL Server seja informado de que houve uma desconexão de rede, ela será confirmada. Em nenhum caso (supondo que você tenha escrito uma única consulta de atualização) o SQL Server executará uma atualização parcial.
Nick Chammas

Respostas:

22

Conforme mencionado por Nick e Martin, o status final da sua consulta depende se o SQL Server conhece o cabo de rede puxado antes da conclusão da consulta. Do Books Online (embora eu ache interessante que haja tópicos equivalentes para isso em 2000 , 2005 , 2008 e 2008 R2 , mas não em 2012 ou 2014):

Se um erro impedir a conclusão bem-sucedida de uma transação, o SQL Server reverterá automaticamente a transação e liberará todos os recursos mantidos pela transação. Se a conexão de rede do cliente com uma instância do Mecanismo de Banco de Dados estiver interrompida, quaisquer transações pendentes para a conexão serão revertidas quando a rede notificar a instância da quebra. Se o aplicativo cliente falhar ou se o computador cliente cair ou for reiniciado, isso também interromperá a conexão, e a instância do Mecanismo de Banco de Dados reverterá quaisquer conexões pendentes quando a rede notificar a interrupção. Se o cliente fizer logoff do aplicativo, quaisquer transações pendentes serão revertidas.

(À parte, essa palavra conexões na 2ª última frase provavelmente deveria ser transações . Não sei como reverter uma conexão.)

De maneira semelhante, o SQL Server pode desfazer ou refazer transações durante a recuperação depois que o servidor for desligado inesperadamente, e isso dependerá do estado da transação no momento do desligamento. Vi pessoas usarem essa tática para conseguir o que você estava tentando fazer (cancelar a (s) transação (ões)) e, quando o servidor foi reiniciado, grande parte do trabalho foi simplesmente refeita (o efeito líquido de sua reação instintiva ficou muito mais próximo a zero do que eles esperavam).

Portanto, em vez de ficar sujeito a isso, em vez de fazer coisas drásticas em pânico, como puxar um cabo de rede ou desligar a máquina, sugiro que no futuro você tenha uma melhor disciplina sobre a execução de consultas ad hoc em sistemas importantes. Por exemplo, em vez de:

UPDATE dbo.sometable 
-- where *oops* I forgot this part

Tenha isto:

BEGIN TRANSACTION;

UPDATE dbo.sometable
-- where *oops* I forgot this part

-- COMMIT TRANSACTION;
-- ROLLBACK TRANSACTION;

Então, se a atualização estava realmente correta, você pode destacar a COMMITpeça e executá-la. Caso contrário, você pode destacar com calma a ROLLBACKpeça e executá-la. Você pode até usar suplementos como o SSMS Tools Pack para editar seu New Querymodelo e incluir esse padrão.

Agora, ainda assim, você poderá ter problemas no caso de executar a consulta e depois não confirmar ou reverter, porque agora sua transação está bloqueando outros usuários. Mas isso é melhor do que modificar dados irrevogavelmente.

E, é claro, como sempre, tenha um backup em que você possa confiar.

Aaron Bertrand
fonte
5
Esse é um excelente conselho e aborda a raiz do problema do OP, mas na verdade não responde à pergunta se a consulta continuou em execução ou não.
Nick Chammas
3
Obrigado @ Nick, minha motivação foi abordar a causa (que estimulou a pergunta), não o sintoma, mas atualizei minha resposta.
Aaron Bertrand
8

@Aaron está correto. Criar uma transação antes dos seus comandos é sua melhor aposta. Se você não se lembra de fazer isso, uma opção é entrar na Tools-Optionsconfiguração e ativar SET IMPLICIT_TRANSACTIONS. Isso iniciará automaticamente uma transação assim que determinados comandos forem executados. Isto inclui UPDATE, DELETEetc. Esta parece ser uma lista bastante completa de qualquer comando que faria "change"alguma coisa. SELECTtambém está incluído na lista e willinicia uma transação. Você pode ver uma lista completa dos comandos que iniciam uma transação com esta configuração aqui . Não criará uma transação se uma já estiver iniciada. Agora, o lado ruim disso é que você terá que se lembrar deCOMMIT depois de qualquer alteração feita.

NOTA: Com base na sugestão de @ Aaron, vou enfatizar novamente isso.

This is very important!  You will have to remember to COMMIT after any change made!

Basicamente, você está trocando o esquecimento de BEGINuma transação e atrapalhando algo, por esquecer COMMITuma transação e deixá-la travada se você a deixar aberta e depois deixar o dia. Eu testei apenas fechando uma janela de consulta pensando que isso reverteria minha transação, no entanto, ele me perguntou se eu queria confirmar ou reverter a transação.

insira a descrição da imagem aqui

Kenneth Fisher
fonte
Na verdade: SELECT vai iniciar uma transação (que também está documentada no link que você postou)
a_horse_with_no_name
Obrigado @a_horse_with_no_name por capturar isso! Eu não li com atenção suficiente e estava saindo de uma memória antiga (isso obviamente estava errado).
Kenneth Fisher
1
Esta é uma publicação útil, mas na verdade não responde à pergunta do OP sobre se a consulta continuou em execução ou não.
Nick Chammas
2
Era um complemento à resposta de @ Aaron. Foi demais para colocar um comentário.
perfil completo de Kenneth Fisher
2

Eu acho que realmente depende:

se o comando já chegar ao servidor antes de você desconectar o cabo de rede, o comando continuará sendo executado normalmente.

se você tiver um TransactionScope (usado em .Net, não sabe outros idiomas) para encapsular todos os comandos de atualização, provavelmente poderá impedir que a transação seja confirmada apenas se o transactionScope.Complete () não tiver sido executado, mas não há garantia. .

Rex
fonte
2
Você disse "se o comando já chegar ao servidor antes de desconectar o cabo de rede, o comando continuará sendo executado normalmente". Isso é contradito pela página BOL do SQL Server à qual Martin vinculou acima. Consulte "Erros durante o processamento de transações" .
Nick Chammas
você está certo. com uma transação especificada, o comando será revertido automaticamente. mas, como experimentamos, quando nenhuma transação foi especificada explicitamente, o comando (uma atualização em lote sem uma transação) foi executado totalmente, mesmo que parássemos nosso aplicativo no meio, o que realmente interrompeu a conexão - mas não é realmente um bom exemplo como o tempo provavelmente não estava correto. Provavelmente é bom fazer alguns testes para que
Rex