SQL Server na prática

Timeouts do SQL Server: cancelamento e novas tentativas

Separe limites de conexão, comando e locks e projete novas tentativas que não dupliquem gravações quando o resultado de uma requisição é incerto.

Um timeout informa que o chamador esgotou seu orçamento de espera. Ele não revela sozinho se o SQL estava lento, bloqueado, cancelado antes do commit ou confirmado antes da perda da resposta. Repetir imediatamente assumindo falha transacional pode transformar latência em operações de negócio duplicadas.

Descobrir qual prazo venceu

O timeout de conexão cobre sua abertura, incluindo rede, autenticação e obtenção de recursos. O timeout de comando diz respeito à execução pelo provedor cliente. SET LOCK_TIMEOUT limita a espera por locks dentro do SQL Server. Esses ajustes tratam de etapas diferentes.

O exemplo altera apenas o orçamento de espera por locks da sessão e depois restaura o valor ilimitado. Ele não limita a duração total de qualquer consulta.

SET LOCK_TIMEOUT 1500;
SELECT @@LOCK_TIMEOUT AS LockTimeoutMilliseconds;
SET LOCK_TIMEOUT -1;

SELECT XACT_STATE() AS TransactionState,
       @@TRANCOUNT AS TransactionCount;

Um lock timeout produz um erro SQL Server classificável. Um timeout de comando normalmente é informado pelo driver e dispara uma solicitação de cancelamento. Registre provedor, detalhes do erro, duração, identificador de correlação e existência de transação ativa. Uma mensagem genérica do framework web não identifica a causa.

Separe também o prazo HTTP do orçamento do comando. Se a camada HTTP desistir sem propagar cancelamento, o banco pode continuar trabalhando. Coordene os limites deixando tempo para limpeza e uma resposta compreensível.

Observar antes de perder o contexto

Durante o incidente, capture esperas, bloqueadores, duração e transações abertas. Estas consultas apenas leem dados e exigem permissões de diagnóstico adequadas à versão.

SELECT
    session_id, request_id, status, command,
    wait_type, wait_time, blocking_session_id,
    total_elapsed_time, cpu_time,
    reads, logical_reads, writes
FROM sys.dm_exec_requests
WHERE session_id <> @@SPID;

SELECT
    session_id, status, open_transaction_count,
    last_request_start_time, last_request_end_time,
    host_name, program_name
FROM sys.dm_exec_sessions
WHERE is_user_process = 1
  AND open_transaction_count > 0;

Uma requisição esperando lock pede investigação diferente de outra consumindo CPU ou aguardando memória. A segunda consulta pode revelar sessões inativas com transações abertas, ausentes da lista de requisições em execução. Nomes de máquina e programa são rótulos fornecidos pelo cliente, não identidades de segurança confiáveis.

Para incidentes recorrentes, relacione horários da aplicação com uma captura direcionada de Extended Events contendo attention e eventos relevantes de conclusão ou erro. Attention evidencia que o cliente pediu interrupção. Não explica se houve ação do usuário, vencimento de prazo ou problema no cliente.

Cancelar não garante que toda transação explícita tenha sofrido rollback. A aplicação deve controlar o ciclo das transações que possui. Depois de uma falha, desfaça a sua quando possível, trate erros de limpeza e descarte uma conexão cujo estado utilizável não consiga determinar. Não dependa apenas de CATCH em SQL: attention não se comporta como qualquer erro T-SQL.

Também não reverta automaticamente uma transação pertencente ao chamador externo sem um contrato. Um componente precisa saber quem inicia, confirma e abandona o trabalho. Essa responsabilidade importa tanto quanto o valor configurado para o timeout.

Repetir com identidade estável

Imagine uma instrução semelhante a um pagamento, confirmada antes da perda da resposta. Uma nova tentativa com outra identidade pode inseri-la duas vezes. Atribua uma chave de idempotência estável ao comando e imponha unicidade no banco. Guarde o resultado necessário para responder quando a mesma chave reaparecer.

O registro de deduplicação e a alteração de negócio precisam confirmar juntos. Gravar a chave primeiro e executar o restante em outra transação permite uma operação incompleta. Se a chave voltar com conteúdo diferente, rejeite a inconsistência.

Use tentativas limitadas com intervalo progressivo apenas para falhas consideradas repetíveis pelo contrato. Multiplicar requisições não resolve uma cadeia longa de bloqueio. Um commit de estado desconhecido exige reconciliar o resultado existente. Teste cancelamento durante execução, durante bloqueio e perda da resposta depois do commit.

Aumentar o prazo pode ser adequado para um export intencionalmente demorado. Mesmo assim, meça quanto recurso ele retém e o efeito nas requisições interativas. O objetivo é ter um limite claro e um resultado transacional conhecido, em vez de apenas adiar a próxima mensagem de erro.

Referências técnicas: Microsoft Learn: Query timeout troubleshooting · Microsoft Learn: SET LOCK_TIMEOUT · Microsoft Learn: XACT_STATE.

Pergunte sobre este artigo

Tem alguma dúvida sobre este tema?

Conte o que você está avaliando ou onde encontrou dificuldades. Responderemos com uma recomendação prática.

Inquiries are not enabled in this preview.

Fazer uma pergunta sobre este artigo