Поделиться через


Устранение ошибок времени ожидания запроса

Симптомы

Предположим, что приложение запрашивает данные из базы данных SQL Server. Если запрос не возвращает данные в пределах настроенного значения времени ожидания (обычно 30 секунд), приложение отменяет запрос и создает одно из следующих сообщений об ошибках:

  • Время ожидания истекло. Время ожидания истекло до завершения операции, либо сервер не отвечает. Выполнение данной инструкции было прервано.

  • System.Data.SqlClient.SqlException. Время ожидания истекло. Время ожидания истекло до завершения операции, либо сервер не отвечает.

Описание

Эти ошибки возникают на стороне приложения. Приложение задает значение времени ожидания и, если достигнуто время ожидания, он отменяет запрос. На стороне SQL Server отмена запроса с клиентской стороны вызывает событие "Внимание", ошибка 3617 (MSSQLSERVER_3617). Если значение времени ожидания на стороне приложения равно 0 (без ограничения времени), ядро СУБД выполняет запрос до завершения.

  • На платформа .NET Framework System.Data.SqlClient значение времени ожидания задается в свойстве CommandTimeout.
  • В API ODBC он устанавливается с помощью атрибута SQL_ATTR_QUERY_TIMEOUT в функции SQLSetStmtAttr .
  • В API Java Database Connectivity (JDBC) оно задается с помощью метода setQueryTimeout.
  • В OLEDB он задается через DBPROP_COMMANDTIMEOUT свойство в DBPROP структуре.
  • В VBA (Excel) оно задается с помощью свойства ADODB.Command.CommandTimeout.

Время ожидания запроса отличается от свойства времени ожидания подключения. Последний определяет время ожидания успешного подключения и не участвует в выполнении запроса. Дополнительные сведения см. в разделе "Время ожидания запроса" не совпадает с временем ожидания подключения.

Действия по устранению неполадок

По крайней мере наиболее распространенная причина времени ожидания запросов является недостаточной производительности запросов. Это означает, что запрос выполняется дольше, чем заданное значение времени ожидания запроса. Чтобы ускорить выполнение запроса, рекомендуется использовать первый целевой объект устранения неполадок. Вот как проверить запросы:

  1. Используйте расширенные события или трассировку SQL, чтобы определить запросы, вызывающие ошибки времени ожидания. Вы можете отслеживать событие внимания вместе с sql_batch_completed расширенными rpc_completed событиями и сопоставлять их на одном и том же session_id. Если вы видите, что завершенное событие сразу же следует за событием внимания, а длительность завершенного события соответствует приблизительно параметру времени ожидания, то вы определили запрос. Приведем пример:

    Примечание.

    В примере SELECT запрос выполнялся почти в течение 30 секунд и остановился. Событие внимания с тем же идентификатором сеанса указывает, что запрос был отменен приложением.

    Имя. Session_id Sql_text Длительность (микросекунд) Метка времени
    sql_batch_started 54 Выберите … from Customers WHERE cid = 192937 NULL 2021-09-30 09:50:25.0000
    sql_batch_completed 54 Выберите … from Customers WHERE cid = 192937 29999981 2021-09-30 09:50:55.0000
    Внимание 54 Выберите … from Customers WHERE cid = 192937 40000 2021-09-30 09:50:55.0400
  2. Выполните и проверьте запросы в SQLCMD или в СРЕДЕ SQL Server Management Studio (SSMS).

  3. Если запросы также медленны в SQLCMD и SSMS, устраняют неполадки и повышают производительность запросов. Подробные сведения см. в разделе "Устранение неполадок медленных запросов в SQL Server"

    Примечание.

    В SQLCMD и SSMS для значения времени ожидания задано значение 0 (без ограничения времени), а запросы можно проверить и исследовать.

  4. Если запросы выполняются быстро в SQLCMD и SSMS, но медленно работают на стороне приложения, измените запросы на использование одинаковых параметров SET, используемых в SQLCMD и SSMS. Сравните параметры SET, собирая трассировку расширенных событий (вход и подключение событий с collect_options_text) и проверяя options_text столбец. Приведем пример:

    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))
    

    Дополнительные сведения см. в статье "Устранение различий в производительности запросов между приложением базы данных и SSMS".

  5. Проверьте, меньше ли CommandTimeout значение параметра ожидаемой длительности запроса. Если параметр пользователя правильно и время ожидания по-прежнему возникает, это связано с проблемой производительности запросов. Ниже приведен пример кода ADO.NET со значением времени ожидания, равным 10 секундам:

    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);
                    }
                }
            }
        }
    }
    

Время ожидания запроса не совпадает с временем ожидания подключения

Время ожидания запроса отличается от времени ожидания подключения или времени ожидания входа. Время ожидания подключения или входа возникает, когда начальное подключение к серверу базы данных достигает предопределенного периода ожидания. На этом этапе запрос не был отправлен серверу. Эти сообщения являются примерами ошибки времени ожидания подключения или входа:

  • Время ожидания для подключения истекло. Истекло время ожидания при попытке использования подтверждения предварительного подтверждения. Это может быть вызвано сбоем подтверждения перед входом или невозможностью ответа сервера вовремя. Время, затраченное на попытки подключиться к этому серверу, составило: [Pre-Login] initialization=23; handshake=14979;

  • Время ожидания истекло. Время ожидания истекло до завершения операции, либо сервер не отвечает. System.ComponentModel.Win32Exception (0x80004005). Время операции ожидания истекло.

Значение времени ожидания подключения — это параметр на стороне клиента и обычно устанавливается значение 15 секунд. Дополнительные сведения об устранении неполадок с временем ожидания подключения см. в статье об устранении неполадок с временем ожидания подключения. Чтобы устранить неполадки с временем ожидания запросов, просмотрите это видео.