Partilhar via


Solucionar problemas de tempo limite de consulta

Sintomas

Suponha que um aplicativo consulte dados de um banco de dados do SQL Server. Se a consulta não retornar nenhum dado dentro do valor de tempo limite configurado (normalmente 30 segundos), o aplicativo cancelará a consulta e gerará uma destas mensagens de erro:

  • O tempo limite expirou. O tempo limite acabou antes da conclusão da operação ou o servidor não está respondendo. A instrução foi finalizada.

  • System.Data.SqlClient.SqlException: o tempo limite da conexão expirou. O tempo limite acabou antes de conclusão da operação ou o servidor não está respondendo.

Explicação

Esses erros ocorrem no lado do aplicativo. O aplicativo define um valor de tempo limite e, se o tempo limite for atingido, ele cancela a consulta. No lado do SQL Server, um cancelamento de consulta do lado do cliente causa um evento Attention, erro 3617 (MSSQLSERVER_3617). Se o valor de tempo limite no lado do aplicativo for definido como 0 (sem limite de tempo), o Mecanismo de Banco de Dados executará a consulta até que ela seja concluída.

O tempo limite da consulta é diferente de uma propriedade de tempo limite da conexão. O último controla quanto tempo esperar por uma conexão bem-sucedida e não está envolvido na execução da consulta. Para obter mais informações, consulte O tempo limite da consulta não é o mesmo que o tempo limite da conexão.

Etapas para solucionar problemas

De longe, o motivo mais comum para tempos limite de consulta são consultas de baixo desempenho. Isso significa que a consulta é executada por mais tempo do que o valor de tempo limite de consulta predefinido. Tornar a consulta mais rápida é o primeiro alvo recomendado da solução de problemas. Veja como verificar consultas:

  1. Use Eventos Estendidos ou Rastreamento SQL para identificar as consultas que causam os erros de tempo limite. Você pode rastrear o evento de atenção junto com os sql_batch_completed eventos estendidos e rpc_completed correlacioná-los no mesmo session_id. Se você observar que um evento concluído é imediatamente seguido por um evento de atenção e a duração do evento concluído corresponde aproximadamente à configuração de tempo limite, você identificou a consulta. Veja um exemplo:

    Observação

    No exemplo, a consulta foi executada SELECT por quase exatamente 30 segundos e parou. O evento attention com a mesma ID de sessão indica que a consulta foi cancelada pelo aplicativo.

    Nome Session_id Sql_text Duração (microssegundos) Timestamp
    sql_batch_started 54 Selecione… de Clientes ONDE cid = 192937 NULO 2021-09-30 09:50:25.0000
    sql_batch_completed 54 Selecione… de Clientes ONDE cid = 192937 29999981 2021-09-30 09:50:55.0000
    Atenção 54 Selecione… de Clientes ONDE cid = 192937 40000 2021-09-30 09:50:55.0400
  2. Execute e teste as consultas no SQLCMD ou no SSMS (SQL Server Management Studio).

  3. Se as consultas também forem lentas no SQLCMD e no SSMS, solucione problemas e melhore o desempenho das consultas. Para obter informações detalhadas, consulte Solucionar problemas de consultas de execução lenta no SQL Server

    Observação

    No SQLCMD e no SSMS, o valor de tempo limite é definido como 0 (sem limite de tempo) e as consultas podem ser testadas e investigadas.

  4. Se as consultas forem rápidas no SQLCMD e no SSMS, mas lentas no lado do aplicativo, altere as consultas para usar as mesmas opções SET usadas no SQLCMD e no SSMS. Compare as opções SET coletando um rastreamento de Eventos Estendidos (logon e conexão de eventos com collect_options_text) e verifique a options_text coluna. Veja um exemplo:

    ALTER EVENT SESSION [setOptions] ON SERVER 
    ADD EVENT sqlserver.existing_connection(SET collect_options_text=(1) 
        ACTION(package0.event_sequence,package0.last_error,sqlos.system_thread_id,sqlserver.context_info,sqlserver.session_id,sqlserver.sql_text)), 
    ADD EVENT sqlserver.login(SET collect_options_text=(1)
        ACTION(sqlos.system_thread_id,sqlserver.context_info,sqlserver.sql_text))
    

    Para obter mais informações, consulte Solucionar problemas de diferença de desempenho de consulta entre o aplicativo de banco de dados e o SSMS.

  5. Verifique se a CommandTimeout configuração é menor que a duração esperada da consulta. Se a configuração do usuário estiver correta e os tempos limite ainda ocorrerem, é devido a um problema de desempenho da consulta. Aqui está um exemplo de código ADO.NET com um valor de tempo limite definido como 10 segundos:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Data.SqlClient;
    using System.Data;
    
    namespace ConsoleApplication6
    {
        class Program
        {
            static void Main()
            {
                string ConnectionString = "Data Source=.\sql2019;Integrated Security=SSPI;Initial Catalog=tempdb;";
                string queryString = "exec test";
    
                using (SqlConnection connection = new SqlConnection(ConnectionString))
                {
                    connection.Open();
                    SqlCommand command = new SqlCommand(queryString, connection);
    
                    // Setting command timeout to 10 seconds
                    command.CommandTimeout = 10;
                    //command.ExecuteNonQuery();
                    try {
                        command.ExecuteNonQuery();
                    }
                    catch (SqlException e) {
                        Console.WriteLine("Got expected SqlException due to command timeout ");
                        Console.WriteLine(e);
                    }
                }
            }
        }
    }
    

O tempo limite da consulta não é o mesmo que o tempo limite da conexão

Um tempo limite de consulta é diferente de um tempo limite de conexão ou tempo limite de login. O tempo limite de conexão ou login ocorre quando a conexão inicial com o servidor de banco de dados atinge um período de tempo limite predefinido. Nesta fase, nenhuma consulta foi enviada ao servidor. Estas mensagens são exemplos de erro de tempo limite de conexão ou login:

  • O tempo limite da conexão expirou. O tempo limite expirou ao tentar consumir a confirmação de handshake de pré-logon. Isso pode ocorrer porque o handshake de pré-logon falhou ou o servidor não pôde responder a tempo. A duração da tentativa de conexão com este servidor foi [Pre-Login] initialization=23; handshake=14979;

  • O tempo limite expirou. O tempo limite acabou antes da conclusão da operação ou o servidor não está respondendo. System.ComponentModel.Win32Exception (0x80004005): a operação de espera atingiu o tempo limite.

O valor do tempo limite da conexão é uma configuração do lado do cliente e normalmente é definido como 15 segundos. Para obter mais informações sobre como solucionar problemas de tempo limite de conexão, consulte solucionar problemas de tempo limite de conexão. Para solução de problemas de tempo limite de consulta, assista a este vídeo.