Tempo limite da transação do SQL Server

9

Existe uma maneira no SQL Server 2008 R2 causar um tempo limite para uma modificação do banco de dados envolvendo uma transação? Temos um cenário em que nosso código de aplicativo trava ou lança uma exceção e falha ao executar uma reversão ou confirmação. Isso faz com que outras sessões sejam interrompidas, aguardando a conclusão da transação.

David Gray Wright
fonte

Respostas:

20

Estendendo a resposta de Marcos ...

Quando ocorre um evento de tempo limite do cliente (.net CommandTimeout, por exemplo), o cliente envia um "ABORT" ao SQL Server. O SQL Server simplesmente abandona o processamento da consulta. Nenhuma transação é revertida, nenhum bloqueio é liberado.

Agora, a conexão é retornada ao pool de conexões, portanto não está fechada no SQL Server. Se isso acontecer (via KILL ou reinicialização do cliente etc), as transações + bloqueios serão apagadas. Observe que sp_reset_connection não os limpa ou não, mesmo que seja anunciado para isso

Esse detrito do aborto irá bloquear outros processos.

A maneira de fazer o SQL Server limpar transações + bloqueios no tempo limite do cliente (estritamente, eventos ABORT) é usar SET XACT_ABORT ON.

Você pode verificar se isso abre duas janelas de consulta no SSMS:

Janela 1:

No menu Query..Query Options, defina um tempo limite de 5 segundos e execute

BEGIN TRAN
UPDATE sometable WITH (TABLOCKX) SET foo = foo WHERE 1 = 0;
WAITFOR DELAY '00:00:10' -- just has to be longer then timeout

Janela 2, isso esperará para sempre (ou atingirá o tempo limite)

SELECT * FROM sometable

SET XACT_ABORT ON também tem efeitos colaterais interessantes:

  • @@ TRANCOUNT é definido como zero na reversão implícita, mas o erro 266 é suprimido (isso acontece se @@ TRANCOUNT for diferente na entrada e na saída de um processo armazenado)
  • XACT_STATE será -1 (está "condenado")

A combinação disso significa que você não pode usar SAVEPOINTS (embora não me lembre do comportamento exato) para confirmações / reversões parciais. O que combina comigo

Links SO no SET XACT_ABORT:

Em procs armazenados aninhados:

Em sp_reset_connection:

gbn
fonte
O futuro diz oi! "Observe que sp_reset_connection não os limpa ou não, mesmo que seja anunciado para fazê-lo" - não acredito que isso seja verdade nas versões mais atualizadas do SQL Server?
kamilk 25/02
11

Estou respondendo com hesitação, pois não há informações suficientes em sua descrição do problema para ter 100% de certeza de que este é o melhor conselho. "Trava ou gera uma exceção" sugere que a origem do problema não foi entendida corretamente, portanto, prossiga com cuidado.

A solução mais simples para isso é provavelmente SET XACT_ABORT ON.

XACT_ABORTdetermina se o SQL Server reverterá uma transação no caso de um erro em tempo de execução. O padrão SET XACT_ABORT OFFreverterá apenas a instrução que causou um erro, deixando qualquer transação pai aberta.

O efeito colateral "pegadinha" da configuração padrão é que um tempo limite pode causar exatamente o mesmo problema, uma transação aberta que é da responsabilidade do cliente manipular e reverter. Se o cliente não tentar / capturar / reverter, a transação permanecerá aberta até que seja atendida (e cito @gbn) a ultra-violência KILL <spid>.

Os artigos frequentemente citados de Erland Sommarskog sobre tratamento de erros no SQL Server contêm todo o plano de fundo e estratégia necessários para lidar com esses cenários e muito mais.

Editar (seguinte comentário): Para identificar transações abertas, sp_whoisactive é provavelmente o recurso mais completo.

Mark Storey-Smith
fonte
Eu encontrei, com alguns pesquisados ​​no Google, maneiras de encontrar transações abertas quando o travamento ocorre - talvez essa seja a melhor solução. Isso é descobrir o que causa a transação não fechada no código e corrigir os buracos no código. Para referência para outros. DBCC OPENTRAN retorna a transação ativa mais antiga -> msdn.microsoft.com/en-us/library/ms182792.aspx Ou algo parecido com isso? -> weblogs.sqlteam.com/mladenp/archive/2008/04/29/…
David Gray Wright
Eu sempre achei que Erland não fazia justiça ao SET XACT_ABORT sommarskog.se/error-handling-I.html#XACT_ABORT
gbn