쿼리 시간 제한 오류 문제 해결

요약

SQL Server 쿼리 시간 제한 오류는 클라이언트 애플리케이션의 명령 제한 시간이 만료되기 전에 쿼리가 데이터를 반환하지 않을 때 발생합니다. 그러면 클라이언트 애플리케이션이 쿼리를 취소하고 "시간 제한 만료됨"을 보고합니다. 이 문서에서는 쿼리 시간 제한(연결 시간 제한이 아님)이 발생했는지 확인하는 방법, 이벤트와 sql_batch_completedrpc_completed 확장 이벤트를 상호 연결하여 attention 특정 쿼리를 식별하는 방법, ADO.NET, ODBC, JDBC, OLE DB 및 ADO에서 명령 시간 제한을 설정하는 방법을 설명합니다. 가장 일반적인 원인은 느린 쿼리이므로 시간 제한 값만 발생시키는 대신 쿼리를 조정하는 것이 좋습니다. 애플리케이션이 시간 제한 오류를 보고하는 동안 SQL Server 구성된 시간 제한과 밀접하게 일치하는 기간으로 주의 이벤트(오류 3617)를 기록하는 경우 이 문서를 사용합니다.

쿼리 시간 제한 오류의 증상

애플리케이션이 SQL Server 데이터베이스의 데이터를 쿼리한다고 가정합니다. 쿼리가 구성된 시간 제한 값(일반적으로 30초) 내에 데이터를 반환하지 않으면 애플리케이션은 쿼리를 취소하고 다음 오류 메시지 중 하나를 생성합니다.

  • 제한 시간이 만료되었습니다. 작업이 완료되기 전에 제한 시간이 초과되었거나 서버가 응답하지 않습니다. 문이 종료되었습니다.

  • System.Data.SqlClient.SqlException: 제한 시간이 만료되었습니다. 작업이 완료되기 전에 제한 시간이 초과되었거나 서버가 응답하지 않습니다.

쿼리 시간 제한 오류가 발생하는 이유

이러한 오류는 애플리케이션 쪽에서 발생합니다. 애플리케이션은 시간 제한 값을 설정하고 시간 제한에 도달하면 쿼리를 취소합니다. SQL Server 쪽에서 클라이언트 쪽에서 쿼리를 취소하면 주의 이벤트인 오류 3617(MSSQLSERVER_3617)이 발생합니다. 애플리케이션 쪽의 시간 제한 값이 0(시간 제한 없음)으로 설정된 경우 데이터베이스 엔진 쿼리가 완료될 때까지 해당 기간(밀리초 또는 일)에 관계없이 쿼리를 실행합니다.

시간 제한 값은 각 데이터 액세스 드라이버 또는 API에 대해 다르게 설정됩니다.

쿼리 시간 제한은 연결 시간 제한 속성과 다릅니다. 후자는 성공적인 연결을 기다리는 시간을 제어하며 쿼리 실행에는 관여하지 않습니다. 자세한 내용은 쿼리 시간 제한이 연결 시간 제한과 동일하지 않음을 참조하세요.

시간이 초과되는 쿼리를 식별하고 해결하는 단계

쿼리 시간 제한의 가장 일반적인 이유는 성능이 저조한 쿼리입니다. 즉, 쿼리가 미리 정의된 쿼리 시간 제한 값보다 오래 실행됩니다. 쿼리를 더 빠르게 실행하여 이 문제를 해결합니다. 쿼리를 확인하는 방법은 다음과 같습니다.

  1. 확장 이벤트 또는 SQL 추적을 사용하여 시간 제한 오류를 발생시키는 쿼리를 식별합니다. 주의rpc_completed동일한 session_id이벤트와 상관 관계를 지정할 수 있습니다. 완료된 이벤트 바로 뒤에 주의 이벤트가 표시되고 완료된 이벤트의 기간이 대략 시간 제한 설정에 해당하는 경우 쿼리를 식별했습니다. 예를 들면 다음과 같습니다.

    참고 항목

    이 예제에서 쿼리는 SELECT 거의 정확히 30초 동안 실행되고 중지됩니다. 세션 ID가 동일한 주의 이벤트는 애플리케이션이 쿼리를 취소했음을 나타냅니다.

    속성 Session_id Sql_text 기간(마이크로초) Timestamp
    sql_batch_started 54 …를 고객의 WHERE cid = 192937 NULL 2021-09-30 09:50:25.0000
    sql_batch_completed 54 …를 고객의 WHERE cid = 192937 29999981 2021-09-30 09:50:55.0000
    주의(Attention) 54 …를 고객의 WHERE cid = 192937 40,000 2021-09-30 09:50:55.0400
  2. sqlcmd 또는 SSMS(SQL Server Management Studio)에서 쿼리를 실행하고 테스트합니다.

  3. sqlcmd 및 SSMS에서도 쿼리 속도가 느린 경우 쿼리의 성능을 개선하고 문제를 해결합니다. 자세한 내용은 SQL Server 느리게 실행되는 쿼리 문제 해결을 참조하세요.

    참고 항목

    sqlcmd 및 SSMS에서 시간 제한 값은 0 (시간 제한 없음)으로 설정되며 쿼리를 테스트하고 조사할 수 있습니다.

  4. 쿼리가 sqlcmd 및 SSMS에서 빠르지만 애플리케이션 쪽에서는 속도가 느린 경우 sqlcmd 및 SSMS에 사용되는 동일한 SET 옵션을 사용하도록 쿼리를 변경합니다. 확장 이벤트 추적(로그인 및 이벤트 연결)을 수집하여 collect_options_textSET 옵션을 비교하고 열을 확인합니다 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 예상 쿼리 기간보다 작은지 확인합니다. 사용자의 설정이 올바르고 시간 제한이 계속 발생하는 경우 쿼리 성능 문제 때문입니다. 시간 제한 값이 10초로 설정된 ADO.NET 코드 예제는 다음과 같습니다.

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

쿼리 시간 제한이 연결 시간 제한과 동일하지 않습니다.

쿼리 시간 제한은 연결 시간 제한 또는 로그인 시간 제한과 다릅니다. 연결 또는 로그인 시간 제한은 데이터베이스 서버에 대한 초기 연결이 미리 정의된 시간 제한 기간에 도달하면 발생합니다. 이 시점에서 클라이언트는 서버에 쿼리를 보내지 않았습니다. 이러한 메시지는 연결 시간 제한 또는 로그인 시간 제한 오류의 예입니다.

  • 연결 시간 제한이 초과하였습니다. 사전 로그인 핸드셰이크 승인을 사용하려고 시도하는 동안 시간 제한이 경과했습니다. 사전 로그인 핸드셰이크가 실패했거나 서버가 시간 내에 다시 응답할 수 없었기 때문일 수 있습니다. 이 서버에 연결하려고 시도할 때 걸린 시간은 [사전 로그인] 초기화=23, 핸드셰이크=14979입니다.

  • 제한 시간이 만료되었습니다. 작업이 완료되기 전에 제한 시간이 초과되었거나 서버가 응답하지 않습니다. System.ComponentModel.Win32Exception(0x80004005): 대기 작업 시간이 초과되었습니다.

연결 제한 시간 값은 클라이언트 쪽 설정이며 일반적으로 15초로 설정됩니다. 연결 시간 제한 문제를 해결하는 방법에 대한 자세한 내용은 연결 시간 제한 오류 문제를 참조하세요.