Solucionar problemas de erros 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 dados 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 período de tempo limite decorreu antes da conclusão da operação ou o servidor não está respondendo. A instrução foi encerrada.
-
System.Data.SqlClient.SqlException: tempo limite expirado O período de tempo limite decorreu antes da 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 cancelará a consulta. No lado do SQL Server, um cancelamento de consulta do lado do cliente causa um evento de Atenção, 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.
- No .NET Framework System.Data.SqlClient, o valor de tempo limite é definido na propriedade CommandTimeout.
- Na API ODBC, ela é definida por meio do atributo
SQL_ATTR_QUERY_TIMEOUT
na função SQLSetStmtAttr . - Na API JDBC (Java Database Connectivity), ela é definida por meio do método setQueryTimeout.
- No OLEDB, ele é definido por meio da propriedade
DBPROP_COMMANDTIMEOUT
na estruturaDBPROP
. - No VBA (Excel), ele é definido por meio da propriedade ADODB.Command.CommandTimeout.
O tempo limite da consulta é diferente de uma propriedade de tempo limite de 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 a solução de problemas
De longe, o motivo mais comum para tempos limite de consulta é o baixo desempenho de consultas. Isso significa que a consulta é executada por mais tempo do que o valor de tempo limite de consulta predefinido. Fazer com que a consulta seja executada mais rapidamente é o primeiro destino recomendado da solução de problemas. Veja como verificar consultas:
Use Eventos Estendidos ou Rastreamento do SQL para identificar as consultas que causam os erros de tempo limite. Você pode rastrear o evento de atenção junto com os eventos estendidos
sql_batch_completed
erpc_completed
e correlacioná-los no mesmosession_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
SELECT
foi executada por quase exatamente 30 segundos e parou. O evento de atenção com a mesma ID de sessão indica que a consulta foi cancelada pelo aplicativo.Nome Session_id Sql_text Duração (microssegundos) Carimbo de data/hora sql_batch_started 54 Selecionar ... de Clientes EM QUE cid = 192937 NULL 30/09/2021 09:50:25.0000 Sql_batch_completed 54 Selecionar ... de Clientes EM QUE cid = 192937 29999981 30/09/2021 09:50:55.0000 Atenção 54 Selecionar ... de Clientes EM QUE cid = 192937 40000 30/09/2021 09:50:55.0400 Execute e teste as consultas no SQLCMD ou SQL Server Management Studio (SSMS).
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 em 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.
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 (entrando e conectando eventos com
collect_options_text
) e verifique a colunaoptions_text
. 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.
Verifique se a configuração
CommandTimeout
é menor que a duração esperada da consulta. Se a configuração do usuário estiver correta e os tempos limite ainda ocorrerem, será devido a um problema de desempenho de 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 de conexão
Um tempo limite de consulta é diferente de um tempo limite de conexão ou tempo limite de logon. O tempo limite de conexão ou logon ocorre quando a conexão inicial com o servidor de banco de dados atinge um período de tempo limite predefinido. Neste estágio, nenhuma consulta foi enviada ao servidor. Essas mensagens são exemplos de erro de tempo limite de conexão ou logon:
-
Tempo Limite de Conexão Expirado. O período de tempo limite decorrido ao tentar consumir a confirmação de handshake de pré-logon. Isso pode ser porque o handshake de pré-logon falhou ou o servidor não pôde responder no tempo. A duração da tentativa de conexão com esse servidor foi [Pre-Login] initialization=23; handshake=14979;
-
O tempo limite expirou. O período de tempo limite decorreu antes da conclusão da operação ou o servidor não está respondendo. System.ComponentModel.Win32Exception (0x80004005): o tempo limite de espera foi atingido.
O valor de 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 solucionar problemas de tempo limite de consulta, assista a este vídeo.