다음을 통해 공유


쿼리 시간 제한 오류 해결

증상

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

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

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

설명

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

  • .NET Framework System.Data.SqlClient에서 제한 시간 값은 CommandTimeout 속성에 설정됩니다.
  • ODBC API에서는 SQLSetStmtAttr 함수의 특성을 통해 SQL_ATTR_QUERY_TIMEOUT 설정됩니다.
  • JDBC(Java Database Connectivity) API에서는 setQueryTimeout 메서드를 통해 설정됩니다.
  • OLEDB에서는 구조체의 DBPROP_COMMANDTIMEOUT 속성을 통해 설정됩니다 DBPROP .
  • VBA(Excel)에서는 ADODB.Command.CommandTimeout 속성을 통해 설정됩니다.

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

문제 해결 단계

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

  1. 확장 이벤트 또는 SQL 추적을 사용하여 시간 제한 오류를 발생시키는 쿼리를 식별합니다. 주의 이벤트를 확장된 이벤트와 rpc_completed sql_batch_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초로 설정됩니다. 연결 시간 제한 문제를 해결하는 방법에 대한 자세한 내용은 연결 시간 제한 문제 해결을 참조하세요. 쿼리 시간 제한 문제 해결은 이 비디오를 시청하세요.