Compartir a través de


Solución de problemas de tiempo de espera de consulta

Síntomas

Supongamos que una aplicación consulta datos de una base de datos de SQL Server. Si la consulta no devuelve ningún dato dentro del valor de tiempo de espera configurado (normalmente 30 segundos), la aplicación cancela la consulta y genera uno de estos mensajes de error:

  • Tiempo de espera agotado. El tiempo de espera transcurrió antes de que se completase la operación, o bien el servidor no responde. Se terminó la instrucción.

  • System.Data.SqlClient.SqlException: tiempo de espera agotado. El tiempo de espera transcurrió antes de que se completase la operación, o bien el servidor no responde.

Explicación

Estos errores se producen en el lado de la aplicación. La aplicación establece un valor de tiempo de espera y, si se alcanza el tiempo de espera, cancela la consulta. En el lado de SQL Server, una cancelación de consulta del lado cliente provoca un evento de atención, error 3617 (MSSQLSERVER_3617). Si el valor de tiempo de espera en la aplicación se establece en 0 (sin límite de tiempo), el Motor de base de datos ejecuta la consulta hasta que se complete.

El tiempo de espera de la consulta es diferente de una propiedad de tiempo de espera de conexión. Este último controla cuánto tiempo esperar una conexión correcta y no está implicado en la ejecución de consultas. Para obtener más información, consulte Tiempo de espera de consulta no es el mismo que el tiempo de espera de conexión.

Pasos para solucionar problemas

De forma lejos, el motivo más común para los tiempos de espera de consulta es que las consultas no superan el rendimiento. Esto significa que la consulta se ejecuta más tiempo que el valor de tiempo de espera de consulta predefinido. Hacer que la consulta se ejecute más rápido es el primer destino recomendado de la solución de problemas. A continuación se muestra cómo comprobar las consultas:

  1. Use eventos extendidos o seguimiento de SQL para identificar las consultas que provocan errores de tiempo de espera. Puede realizar un seguimiento del evento de atención junto con los sql_batch_completed eventos extendidos y rpc_completed y correlacionarlos en el mismo session_id. Si observa que un evento completado va seguido inmediatamente de un evento de atención y la duración del evento completado se corresponde aproximadamente con la configuración de tiempo de espera, ha identificado la consulta. Este es un ejemplo:

    Nota:

    En el ejemplo, la SELECT consulta se ejecutó durante casi exactamente 30 segundos y se detuvo. El evento de atención que tiene el mismo identificador de sesión indica que la aplicación canceló la consulta.

    Nombre Session_id Sql_text Duración (microsegundos) Marca de tiempo
    sql_batch_started 54 Seleccione … from Customers WHERE cid = 192937 NULL 2021-09-30 09:50:25.0000
    sql_batch_completed 54 Seleccione … from Customers WHERE cid = 192937 29999981 2021-09-30 09:50:55.0000
    Atención 54 Seleccione … from Customers WHERE cid = 192937 40000 2021-09-30 09:50:55.0400
  2. Ejecute y pruebe las consultas en SQLCMD o en SQL Server Management Studio (SSMS).

  3. Si las consultas también son lentas en SQLCMD y SSMS, solucione problemas y mejore el rendimiento de las consultas. Para obtener información detallada, consulte Solución de problemas de consultas de ejecución lenta en SQL Server.

    Nota:

    En SQLCMD y SSMS, el valor de tiempo de espera se establece en 0 (sin límite de tiempo) y las consultas se pueden probar e investigar.

  4. Si las consultas son rápidas en SQLCMD y SSMS, pero lentamente en la aplicación, cambie las consultas para usar las mismas opciones SET que se usan en SQLCMD y SSMS. Compare las opciones SET mediante la recopilación de un seguimiento de eventos extendidos (inicio de sesión y conexión de eventos con collect_options_text) y compruebe la options_text columna. Este es un ejemplo:

    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 más información, consulte Solución de problemas de diferencias de rendimiento de consultas entre la aplicación de base de datos y SSMS.

  5. Compruebe si la CommandTimeout configuración es menor que la duración esperada de la consulta. Si la configuración del usuario es correcta y se siguen produciendo tiempos de espera, se debe a un problema de rendimiento de consultas. Este es un ejemplo de código de ADO.NET con un valor de tiempo de espera establecido en 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);
                    }
                }
            }
        }
    }
    

El tiempo de espera de la consulta no es el mismo que el tiempo de espera de conexión.

Un tiempo de espera de consulta es diferente de un tiempo de espera de conexión o un tiempo de espera de inicio de sesión. El tiempo de espera de conexión o inicio de sesión se produce cuando la conexión inicial al servidor de bases de datos alcanza un período de tiempo de espera predefinido. En esta fase, no se ha enviado ninguna consulta al servidor. Estos mensajes son ejemplos de error de tiempo de espera de inicio de sesión o conexión:

  • Tiempo de espera de conexión agotado. El período de tiempo de espera transcurrió al intentar consumir la confirmación del protocolo de enlace previo al inicio de sesión. Esto podría deberse a un error en el protocolo de enlace previo al inicio de sesión o a que el servidor no pudo responder a tiempo. El tiempo invertido al intentar conectarse a este servidor fue: [Previo al inicio de sesión] inicialización=23; protocolo de enlace=14979;

  • Tiempo de espera agotado. El tiempo de espera transcurrió antes de que se completase la operación, o bien el servidor no responde. System.ComponentModel.Win32Exception (0x80004005): se agotó el tiempo de espera de la operación wait.

El valor de tiempo de espera de conexión es una configuración del lado cliente y normalmente se establece en 15 segundos. Para obtener más información sobre cómo solucionar problemas de tiempo de espera de conexión, consulte Solución de problemas de tiempo de espera de conexión. Para solucionar problemas de tiempo de espera de consulta, vea este vídeo.