다음을 통해 공유


Always On 가용성 그룹에 대한 성능 모니터링

적용 대상:SQL Server

Always On 가용성 그룹의 성능 측면은 중요 업무용 데이터베이스에 대한 SLA(서비스 수준 계약)를 유지하는 데 매우 중요합니다. 가용성 그룹이 로그를 보조 복제본(replica) 배포하는 방법을 이해한다면 가용성 구현의 RTO(복구 시간 목표) 및 RPO(복구 지점 목표)를 예측하며 성능이 저조한 가용성 그룹 또는 복제본(replica) 병목 상태를 식별하는 데 도움을 줄 수 있습니다. 이 문서에서는 동기화 프로세스를 설명하고, 일부 주요 메트릭을 계산하는 방법을 보여 주며, 일반적인 성능 문제 해결 시나리오에 대한 링크를 제공합니다.

데이터 동기화 프로세스

전체 동기화 시간을 예측하고 병목 상태를 식별하려면 동기화 프로세스를 이해해야 합니다. 성능 병목 상태는 프로세스의 어디에서나 발생할 수 있으며, 병목 상태를 찾는다면 기본 문제를 더 깊이 이해하는 데 도움이 될 수 있습니다. 다음 그림과 표에서 데이터 동기화 프로세스를 보여주고 있습니다:

가용성 그룹 데이터 동기화의 스크린샷.

시퀀스 단계 설명 댓글 유용한 메트릭
1 로그 생성 로그 데이터는 디스크에 플러시됩니다. 이 로그는 보조 복제본(replica)에 복제되어야 합니다. 로그 레코드는 송신 큐에 들어갑니다. SQL Server:데이터베이스 > 로그 바이트 플러시/초
2 캡처 각 데이터베이스에 대한 로그가 캡처되어 해당 파트너 큐(데이터베이스-복제본 쌍당 하나씩)로 전송됩니다. 이 캡처 프로세스는 가용성 복제본이 연결되어 있고 어떤 이유로든 데이터 이동이 일시 중단되지 않고 데이터베이스-복제본 쌍이 동기화 또는 동기화된 것으로 표시되는 한 지속적으로 실행됩니다. 캡처 프로세스가 메시지를 충분히 빠르게 검색하고 큐에 넣기를 할 수 없는 경우 로그 송신 큐가 빌드됩니다. SQL Server:가용성 복제본 > 복제본으로 보낸 바이트/초- 해당 가용성 복제본에 대해 큐에 대기 중인 모든 데이터베이스 메시지의 합계를 집계한 값입니다.

기본 복제본에서의 log_send_queue_size (KB) 및 log_bytes_send_rate (KB/초).
3 전송 각 데이터베이스-복제본 큐의 메시지는 큐에서 제거되고 유선을 통해 해당 보조 복제본으로 전송됩니다. SQL Server:Availability Replica > 전송됨 바이트/초
4 수신 및 캐시 각 보조 복제본(replica) 메시지를 수신하며 캐시 합니다. 성능 카운터 SQL Server:Availability Replica > Log Bytes Received/sec
5 강화 강화를 위해서는 보조 복제본에서 로그가 플러시 됩니다. 로그 플러시 후 확인 메시지가 기본 레플리카로 전송됩니다.

로그가 강화되면 데이터 손실은 방지됩니다.
성능 카운터 SQL Server:Database > Log Bytes Flushed/sec
대기 유형 HADR_LOGCAPTURE_SYNC
6 다시 실행 보조 복제본의 플러시된 페이지를 다시 처리합니다. 페이지가 다시 실행되기를 기다리고 있는 동안 다시 실행 큐에 유지됩니다. SQL Server:Database Replica > Redone Bytes/sec

redo_queue_size(KB) 및 redo_rate.
대기 유형 REDO_SYNC

흐름 제어 게이트

가용성 그룹은 모든 가용성 복제본(replica) 네트워크 및 메모리 리소스와 같은 과도한 리소스 소비를 방지하기 위하여 기본 복제본(replica) 흐름 제어 게이트를 사용하여 만들어졌습니다. 이러한 흐름 제어 게이트는 가용성 복제본의 동기화 상태에 영향을 주지 않지만 RPO를 비롯한 가용성 데이터베이스의 전반적인 성능에 영향을 줄 수 있습니다.

기본 복제본(replica) 로그를 캡처한 후 두 가지 수준의 흐름 제어가 적용됩니다. 두 게이트의 메시지 임계값에 도달하면 로그 메시지는 특정 복제본(replica) 또는 특정 데이터베이스로 더 이상 전송되지 않습니다. 보낸 메시지에 대한 승인 메시지가 수신되면 메시지를 전송하여 보낸 메시지 수를 임계값 아래로 가져올 수 있습니다.

흐름 제어 게이트 외에도 로그 메시지가 전송되지 않도록 할 수 있는 또 다른 요소가 있습니다. 복제본(replica)을 동기화하면 메시지가 LSN(로그 시퀀스 번호)의 순서대로 전송되며 적용됩니다. 로그 메시지를 보내기 전에 해당 LSN은 가장 낮은 승인된 LSN 번호에 대해서도 확인하여 메시지 유형에 따라 임계값 중 하나 미만인지 확인합니다. 두 LSN 숫자 사이의 간격이 임계값보다 크면 메시지가 전송되지 않습니다. 간격이 다시 임계값보다 미만이 되면 메시지가 전송됩니다.

SQL Server 2022(16.x)는 각 게이트에서 허용하는 메시지 수에 대한 제한을 증가합니다. 추적 플래그 12310을 사용하면 SQL Server 2019(15.x) CU9, SQL Server 2017(14.x) CU18, SQL Server 2016(13.x) SP1 CU16 버전에서도 증가된 제한을 사용할 수 있습니다.

다음 표에서는 메시지 제한을 비교하고 있습니다:

추적 플래그 12310, 즉 SQL Server 2022(16.x), SQL Server 2019(15.x) CU9, SQL Server 2017(14.x) CU18, SQL Server 2016(13.x) SP1 CU16 이상 버전을 사용하도록 설정하는 SQL Server 버전의 경우 다음 제한을 참조하세요.

수준 게이트 수 메시지 수 유용한 메트릭
운송 가용성 복제본 당 1 16384 확장 이벤트 database_transport_flow_control_action
데이터베이스 가용성 데이터베이스당 1개 7168 DBMIRROR_SEND

확장 이벤트 hadron_database_flow_control_action

두 가지 유용한 성능 카운터 SQL Server:Availability Replica > Flow control/secSQL Server:Availability Replica > Flow Control Time (ms/sec)은 마지막 초 이내에 흐름 제어가 활성화된 시간 및 흐름 제어를 하기 위해 대기하면서 소비한 시간도 보여 줍니다. 흐름 제어에 대한 대기 시간이 길어질수록 RPO가 높아집니다. 흐름 제어에서 높은 대기 시간을 발생시킬 수 있는 문제 유형에 대한 자세한 내용은 문제 해결: 비동기-커밋 가용성 그룹 복제본을 사용한 잠재적인 데이터 손실을 참조하세요.

RTO(장애 조치(failover) 시간 예측)

SLA의 RTO는 언제든지 Always On 구현의 장애 조치(failover) 시간에 따라 달라지고, 이는 다음 수식으로 표현할 수 있습니다:

가용성 그룹 RTO 계산의 스크린샷

중요한

가용성 그룹이 가용성 데이터베이스를 두 개 이상 포함하는 경우 Tfailover가 가장 높은 가용성 데이터베이스가 RTO 준수를 위한 제한 값이 됩니다.

오류 감지 시간인 Tdetection은 시스템이 오류를 감지하는 데 걸리는 시간입니다. 이 시간은 클러스터 수준 설정에 따라 달라지며 개별 가용성 복제본에 의존하지 않습니다. 구성된 자동 장애 조치 조건에 따라, 고립된 스핀락과 같은 중요 SQL Server 내부 오류에 즉각 대응하여 장애 조치가 트리거될 수 있습니다. 이 경우 검색은 sp_server_diagnostics 오류 보고서가 WSFC(Windows Server 장애 조치(failover) 클러스터)로 전송되는 속도만큼 빠를 수 있습니다. 기본 간격은 상태 검사 시간 제한의 1/3입니다. 클러스터 상태 검사 제한 시간이 만료되었거나(기본적으로 30초) 리소스 DLL과 SQL Server 인스턴스 간의 임대가 만료된 경우(기본적으로 20초) 시간 제한으로 인해 장애 조치(failover)를 트리거할 수도 있습니다. 이 경우 탐지 시간은 타임아웃 간격만큼 깁니다. 자세한 내용은 SQL Server의 가용성 그룹 자동 장애 조치에 대한 유연한 장애 조치 정책을 참조하세요.

보조 복제본이 장애 조치(failover)를 위해 해야 할 유일한 작업은 로그의 끝까지 다시 실행하는 것 뿐입니다. 다시 실행 시간인 Tredo는 다음 공식을 사용해서 계산됩니다:

가용성 그룹 재실행 시간 계산의 스크린샷

단, redo_queueredo_queue_size의 값이고 redo_rateredo_rate의 값입니다.

오버헤드 시간인 Toverhead는 WSFC 클러스터의 장애 조치와 데이터베이스를 온라인 상태로 전환하는 데 걸리는 시간을 포함합니다. 이 시간은 보통 짧고 일정합니다.

잠재적인 데이터 손실 예측(RPO)

SLA의 RPO는 언제든지 Always On 실행으로 발생할 수 있는 데이터 손실에 따라 달라집니다. 이러한 예상 데이터 손실은 다음 수식으로 나타낼 수 있습니다:

가용성 그룹 RPO 계산의 스크린샷

여기서, log_send_queuelog_send_queue_size의 값이며 log generation rateSQL Server:Database > Log Bytes Flushed/sec의 값입니다.

경고

가용성 그룹이 가용성 데이터베이스를 두 개 이상 포함하는 경우 Tdata_loss가 가장 높은 가용성 데이터베이스가 RPO 준수를 하기 위한 제한값이 됩니다.

로그 전송 큐는 치명적인 오류로 인해 손실될 수 있는 모든 데이터를 나타냅니다. 언뜻 보기에 로그 생성 속도가 로그 전송 속도 대신 사용되는지 궁금합니다( log_send_rate 참조). 그러나 로그 전송 속도를 사용하면 동기화할 시간만 제공되고 RPO는 동기화 속도가 아니라 생성 속도에 따라 데이터 손실을 측정합니다.

Tdata_loss를 추정하는 간단한 방법은 last_commit_time 사용하는 것입니다. 기본 복제본 DMV는 모든 복제본에 대해 이 값을 보고합니다. 기본 복제본(replica) 값과 보조 복제본(replica) 값 간의 차이를 계산하여 보조 복제본(replica) 로그가 기본 복제본(replica)을 얼마나 빨리 따라잡는지 예측할 수 있습니다. 앞에서 설명한 것처럼 이 계산은 로그가 생성되는 속도에 따라 잠재적인 데이터 손실을 알려주지는 않지만 근사치에 가깝습니다.

SSMS 대시보드를 사용하여 RTO 및 RPO 예측

Always On 가용성 그룹에서 RTO 및 RPO는 보조 복제본에 호스트된 데이터베이스에 대해 계산되고 표시됩니다. SSMS(SQL Server Management Stuiod) 대시보드의 주 복제본에서 RTO 및 RPO는 보조 복제본별로 그룹화됩니다.

대시보드 내에서 RTO 및 RPO를 보려면 다음 단계를 수행합니다.

  1. SQL Server Management Studio에서 Always On 고가용성노드를 확장하고 가용성 그룹의 이름을 마우스 오른쪽 단추로 클릭한 후 대시보드 표시를 선택합니다.

  2. 그룹별 탭에서 열 추가/제거를 선택합니다. 예상 복구 시간(초)[RTO] 및 예상 데이터 손실(시간) [RPO]를 모두 확인합니다.

    RTO RPO 대시보드를 보여 주는 스크린샷

보조 데이터베이스 RTO 계산

복구 시간 계산은 장애 조치(failover) 발생 후 보조 데이터베이스를 복구하는 데 필요한 시간을 결정합니다. 장애 조치 시간은 보통 짧고 일정합니다. 탐지 시간은 개별 가용성 복제본이 아닌 클러스터 수준의 설정에 따라 달라집니다.

보조 데이터베이스(DB_sec)의 경우 RTO의 계산 및 표시는 redo_queue_sizeredo_rate를 기반으로 합니다.

RTO 계산의 스크린샷

코너 사례를 제외하고는 보조 데이터베이스의 RTO를 계산하는 수식은 다음과 같습니다:

RTO를 계산하는 수식의 스크린샷

보조 데이터베이스 RPO 계산

보조 데이터베이스(DB_sec)의 경우, RPO의 계산 및 표시는 해당 데이터베이스의 is_failover_ready, last_commit_time 값과 이에 상관된 주 데이터베이스(DB_pri)의 last_commit_time 값을 기반으로 합니다. 값 DB_sec.is_failover_ready 이면 1주 데이터베이스와 보조 데이터베이스 간의 데이터가 동기화되고 장애 조치 시 데이터 손실이 발생하지 않습니다. 그러나 이 값이 0면 주 데이터베이스와 보조 데이터베이스 간에 last_commit_time 간격이 last_commit_time 있습니다.

주 데이터베이스의 last_commit_time 경우 최신 트랜잭션이 커밋된 시간입니다. 보조 데이터베이스의 last_commit_time 경우 보조 데이터베이스에서도 성공적으로 강화된 주 데이터베이스의 트랜잭션에 대한 최신 커밋 시간입니다. 이 숫자는 주 데이터베이스와 보조 데이터베이스 모두에 대해 동일합니다. 그러나 이러한 두 값 간의 간격은 보류 중인 트랜잭션이 보조 데이터베이스에서 강화되지 않은 기간이며 장애 조치(failover) 시 손실될 수 있습니다.

RPO 계산 스크린샷

RTO/RPO 수식에 사용되는 성능 메트릭

  • redo_queue_size (KB): RTO에 사용되는 다시 실행 큐의 크기는 last_received_lsnlast_redone_lsn 사이의 트랜잭션 로그 크기입니다. last_received_lsn 값은 이 보조 데이터베이스를 호스트하는 보조 복제본에서 모든 로그 블록이 수신된 지점을 식별하는 로그 블록 ID입니다. 값 last_redone_lsn 은 보조 데이터베이스에서 다시 실행된 마지막 로그 레코드의 로그 시퀀스 번호입니다. 이 두 값을 기반으로 시작 로그 블록() 및 끝last_redone_lsn 로그 블록(last_received_lsn)의 ID를 찾을 수 있습니다. 이 두 로그 블록 사이의 공간은 아직 다시 실행되지 않은 트랜잭션 로그 블록 수를 나타낼 수 있습니다. 이것은 KB(킬로바이트)로 측정됩니다.

  • redo_rate (KB/초): RTO 계산에 사용되는 누적 값은 초당 보조 데이터베이스에서 다시 실행되거나 재생된 트랜잭션 로그(KB)의 양을 보여 줍니다.

  • last_commit_time (datetime): RPO에서 사용되는 이 값은 주 데이터베이스와 보조 데이터베이스 간에 의미가 다릅니다. 주 데이터베이스 last_commit_time 의 경우 최신 트랜잭션이 커밋된 시간입니다. 보조 데이터베이스의 경우, 주 데이터베이스의 트랜잭션에 대해 보조 데이터베이스에서 확정된 최신 커밋은 last_commit_time입니다. 보조 데이터베이스의 이 값은 주 데이터베이스의 동일한 값과 함께 동기화되어야 하므로 이 두 값 간의 간격은 RPO(데이터 손실)의 추정치입니다.

DMV를 사용한 RTO 및 RPO 예측

DMV sys.dm_hadr_database_replica_states 쿼리하고 sys.dm_hadr_database_replica_cluster_states 데이터베이스의 RPO 및 RTO를 예측할 수 있습니다. 다음 쿼리는 두 작업을 모두 실행하는 저장 프로시저를 만듭니다.

참고

RTO를 추정하기 위한 저장 프로시저를 먼저 생성하고 실행해야 합니다. 이는 RPO를 추정하기 위한 저장 프로시저를 실행하려면 필수적인 값이기 때문입니다.

RTO를 예측하기 위한 저장 프로시저 만들기

  1. 대상 보조 복제본에서 저장 프로시저 proc_calculate_RTO를 만듭니다. 이 저장 프로시저가 이미 있는 경우 먼저 삭제한 다음 다시 만듭니다.

    IF object_id(N'proc_calculate_RTO', 'p') IS NOT NULL
        DROP PROCEDURE proc_calculate_RTO;
    GO
    
    RAISERROR ('creating procedure proc_calculate_RTO', 0, 1)
        WITH NOWAIT;
    GO
    
    -- name: proc_calculate_RTO
    --
    -- description: Calculate RTO of a secondary database.
    -- 
    -- parameters: @secondary_database_name nvarchar(max): name of the secondary database.
    --
    -- security: this is a public interface object.
    --
    CREATE PROCEDURE proc_calculate_RTO
    @secondary_database_name NVARCHAR (MAX)
    AS
    BEGIN
        DECLARE @db AS sysname;
        DECLARE @is_primary_replica AS BIT;
        DECLARE @is_failover_ready AS BIT;
        DECLARE @redo_queue_size AS BIGINT;
        DECLARE @redo_rate AS BIGINT;
        DECLARE @replica_id AS UNIQUEIDENTIFIER;
        DECLARE @group_database_id AS UNIQUEIDENTIFIER;
        DECLARE @group_id AS UNIQUEIDENTIFIER;
        DECLARE @RTO AS FLOAT;
        SELECT @is_primary_replica = dbr.is_primary_replica,
               @is_failover_ready = dbcs.is_failover_ready,
               @redo_queue_size = dbr.redo_queue_size,
               @redo_rate = dbr.redo_rate,
               @replica_id = dbr.replica_id,
               @group_database_id = dbr.group_database_id,
               @group_id = dbr.group_id
        FROM sys.dm_hadr_database_replica_states AS dbr
             INNER JOIN sys.dm_hadr_database_replica_cluster_states AS dbcs
                 ON dbr.replica_id = dbcs.replica_id
                AND dbr.group_database_id = dbcs.group_database_id
        WHERE dbcs.database_name = @secondary_database_name;
        IF @is_primary_replica IS NULL
           OR @is_failover_ready IS NULL
           OR @redo_queue_size IS NULL
           OR @replica_id IS NULL
           OR @group_database_id IS NULL
           OR @group_id IS NULL
            BEGIN
                PRINT 'RTO of Database ' + @secondary_database_name + ' is not available';
                RETURN;
            END
        ELSE
            IF @is_primary_replica = 1
                BEGIN
                    PRINT 'You are visiting wrong replica';
                    RETURN;
                END
        IF @redo_queue_size = 0
            SET @RTO = 0;
        ELSE
            IF @redo_rate IS NULL
               OR @redo_rate = 0
                BEGIN
                    PRINT 'RTO of Database ' + @secondary_database_name + ' is not available';
                    RETURN;
                END
            ELSE
                SET @RTO = CAST (@redo_queue_size AS FLOAT) / @redo_rate;
        PRINT 'RTO of Database ' + @secondary_database_name + ' is ' + CONVERT (VARCHAR, ceiling(@RTO));
        PRINT 'group_id of Database ' + @secondary_database_name + ' is ' + CONVERT (NVARCHAR (50), @group_id);
        PRINT 'replica_id of Database ' + @secondary_database_name + ' is ' + CONVERT (NVARCHAR (50), @replica_id);
        PRINT 'group_database_id of Database ' + @secondary_database_name + ' is ' + CONVERT (NVARCHAR (50), @group_database_id);
    END
    
  2. proc_calculate_RTO를 대상 보조 데이터베이스 이름으로 실행합니다.

    EXECUTE proc_calculate_RTO @secondary_database_name = N'DB_sec';
    
  3. 출력은 대상 보조 복제본(replica) 데이터베이스의 RTO 값을 표시합니다. RPO 추정 저장 프로시저에 사용할 group_id, replica_idgroup_database_id를 저장합니다.

    샘플 출력:

    RTO of Database DB_sec' is 0
    group_id of Database DB4 is F176DD65-C3EE-4240-BA23-EA615F965C9B
    replica_id of Database DB4 is 405554F6-3FDC-4593-A650-2067F5FABFFD
    group_database_id of Database DB4 is 39F7942F-7B5E-42C5-977D-02E7FFA6C392
    

RPO를 예측하기 위한 저장 프로시저 만들기

  1. 주 복제본에서 저장 프로시저 proc_calculate_RPO를 만듭니다. 이미 있는 경우 그것을 먼저 삭제한 다음 다시 만듭니다.

    IF object_id(N'proc_calculate_RPO', 'p') IS NOT NULL
        DROP PROCEDURE proc_calculate_RPO;
    GO
    
    RAISERROR ('creating procedure proc_calculate_RPO', 0, 1)
        WITH NOWAIT;
    GO
    
    -- name: proc_calculate_RPO
    --
    -- description: Calculate RPO of a secondary database.
    -- 
    -- parameters: @group_id uniqueidentifier: group_id of the secondary database.
    --             @replica_id uniqueidentifier: replica_id of the secondary database.
    --             @group_database_id uniqueidentifier: group_database_id of the secondary database.
    --
    -- security: this is a public interface object.
    --
    CREATE PROCEDURE proc_calculate_RPO
    @group_id UNIQUEIDENTIFIER, @replica_id UNIQUEIDENTIFIER, @group_database_id UNIQUEIDENTIFIER
    AS
    BEGIN
        DECLARE @db_name AS sysname;
        DECLARE @is_primary_replica AS BIT;
        DECLARE @is_failover_ready AS BIT;
        DECLARE @is_local AS BIT;
        DECLARE @last_commit_time_sec AS DATETIME;
        DECLARE @last_commit_time_pri AS DATETIME;
        DECLARE @RPO AS NVARCHAR (MAX);
        SELECT @db_name = dbcs.database_name,
               @is_failover_ready = dbcs.is_failover_ready,
               @last_commit_time_sec = dbr.last_commit_time
        FROM sys.dm_hadr_database_replica_states AS dbr
             INNER JOIN sys.dm_hadr_database_replica_cluster_states AS dbcs
                 ON dbr.replica_id = dbcs.replica_id
                AND dbr.group_database_id = dbcs.group_database_id
        WHERE dbr.group_id = @group_id
              AND dbr.replica_id = @replica_id
              AND dbr.group_database_id = @group_database_id;
        SELECT @last_commit_time_pri = dbr.last_commit_time,
               @is_local = dbr.is_local
        FROM sys.dm_hadr_database_replica_states AS dbr
             INNER JOIN sys.dm_hadr_database_replica_cluster_states AS dbcs
                 ON dbr.replica_id = dbcs.replica_id
                AND dbr.group_database_id = dbcs.group_database_id
        WHERE dbr.group_id = @group_id
              AND dbr.is_primary_replica = 1
              AND dbr.group_database_id = @group_database_id;
        IF @is_local IS NULL
           OR @is_failover_ready IS NULL
            BEGIN
                PRINT 'RPO of database ' + @db_name + ' is not available';
                RETURN;
            END
        IF @is_local = 0
            BEGIN
                PRINT 'You are visiting wrong replica';
                RETURN;
            END
        IF @is_failover_ready = 1
            SET @RPO = '00:00:00';
        ELSE
            IF @last_commit_time_sec IS NULL
               OR @last_commit_time_pri IS NULL
                BEGIN
                    PRINT 'RPO of database ' + @db_name + ' is not available';
                    RETURN;
                END
            ELSE
                BEGIN
                    IF DATEDIFF(ss, @last_commit_time_sec, @last_commit_time_pri) < 0
                        BEGIN
                            PRINT 'RPO of database ' + @db_name + ' is not available';
                            RETURN;
                        END
                    ELSE
                        SET @RPO = CONVERT (VARCHAR, DATEADD(ms, datediff(ss, @last_commit_time_sec, @last_commit_time_pri) * 1000, 0), 114);
                END
        PRINT 'RPO of database ' + @db_name + ' is ' + @RPO;
    END
    
    -- secondary database's last_commit_time -- correlated primary database's last_commit_time
    
  2. proc_calculate_RPO을(를) 대상 보조 데이터베이스의 group_id, replica_id, 및 group_database_id로 실행합니다.

    EXECUTE proc_calculate_RPO
        @group_id = 'F176DD65-C3EE-4240-BA23-EA615F965C9B',
        @replica_id = '405554F6-3FDC-4593-A650-2067F5FABFFD',
        @group_database_id = '39F7942F-7B5E-42C5-977D-02E7FFA6C392';
    
  3. 출력은 대상 보조 복제본(replica) 데이터베이스의 RPO 값을 표시합니다.

RTO 및 RPO 모니터링

이 섹션에서는 RTO 및 RPO 메트릭에 대한 가용성 그룹을 모니터링하는 방법을 설명합니다. 이 시연은 Always On 상태 모델, 2부: 상태 모델 확장에 제공된 GUI 자습서와 비슷합니다.

장애 조치 시간 예측(RTO) 및 잠재적 데이터 손실 예측(RPO)에서 장애 조치 시간과 잠재적 데이터 손실 계산의 요소는 정책 관리 패싯 데이터베이스 복제본 상태에 성능 메트릭으로 편리하게 제공됩니다. 자세한 내용은 SQL Server 개체의 정책 기반 관리 패싯 보기를 참조하세요. 일정에 따라 이러한 두 메트릭을 모니터링하고 메트릭이 RTO 및 RPO를 각각 초과하면 경고를 받을 수 있습니다.

시연된 스크립트는 다음과 같은 특징을 가지고 해당 일정에 따라서 실행되는 두 개의 시스템 정책을 만듭니다:

  • 5분마다 평가되는, 예상 장애 조치 시간이 10분을 초과할 때 실패하는 RTO 정책

  • 예상 데이터 손실이 1시간을 초과할 때 실패하는 RTO 정책이며, 이는 30분마다 평가됩니다

  • 두 정책은 모든 가용성 복제본(replica)에 관하여 동일한 구성을 갖습니다

  • 정책은 모든 서버에서 평가되지만 로컬 가용성 복제본이 기본 복제본인 가용성 그룹에 대해서만 평가됩니다. 로컬 가용성 복제본이 주 복제본이 아닌 경우 정책이 평가되지 않습니다.

  • 정책 오류는 기본 복제본(replica)에서 볼 때면 Always On 대시보드에 편리하게 표시됩니다.

정책을 만들려면 가용성 그룹에 참여하는 모든 서버 인스턴스에서 다음 지침을 따릅니다.

  1. 아직 시작되지 않은 경우 SQL Server 에이전트 서비스를 시작합니다.

  2. SQL Server Management Studio의 도구 메뉴에서 옵션선택합니다.

  3. SQL Server Always On 탭에서 사용자 정의 Always On 정책 사용을 선택하고 확인을 선택합니다.

    이 설정을 활성화하면 Always On 대시보드에 적절히 구성된 사용자 지정 정책을 표시할 수 있습니다.

  4. 다음 사양을 사용하여 정책 기반 관리 조건을 만듭니다:

    • 이름: RTO
    • 패싯: 데이터베이스 복제본 상태
    • 필드: Add(@EstimatedRecoveryTime, 60)
    • 연산자: <=
    • : 600

    잠재적인 장애 조치 시간이 10분을 넘을 경우, 장애 검색 및 장애 조치 모두에 대한 60초 오버헤드를 포함하여, 이 조건이 실패합니다.

  5. 다음 사양을 사용하여 2차 정책 기반 관리 조건을 만듭니다:

    • 이름: RPO
    • 패싯: 데이터베이스 복제본 상태
    • 필드: @EstimatedDataLoss
    • 연산자: <=
    • : 3600

    잠재적인 데이터 손실이 1시간을 초과할 때 이 조건은 실패합니다.

  6. 다음 사양을 사용하여 3차 정책 기반 관리 조건을 만듭니다:

    • 이름: IsPrimaryReplica
    • 패싯: 가용성 그룹
    • 필드: @LocalReplicaRole
    • 연산자 :=
    • : Primary

    이 조건은 지정된 가용성 그룹의 로컬 가용성 복제본(replica)이 기본 복제본(replica)인지 여부를 확인합니다.

  7. 다음 사양을 사용하여 정책 기반 관리 조건을 만듭니다:

    • 일반 페이지:

      • 이름: CustomSecondaryDatabaseRTO

      • 상태 확인: RTO

      • 대상에 대한: IsPrimaryReplica AvailabilityGroup의 모든 DatabaseReplicaState

        이 설정을 사용하면 로컬 가용성 복제본이 기본 복제본인 가용성 그룹에 관해서만 정책은 평가됩니다.

        • 평가 모드: 일정에 따라

        • 일정: CollectorSchedule_Every_5min

        • 활성화됨: 선택됨

    • 설명 페이지:

      • 범주: 가용성 데이터베이스 경고

        이 설정을 통해 정책 평가 결과가 Always On 대시보드에 표시될 수 있습니다.

        • 설명: 현재 복제본(replica) 검색 및 장애 조치(failover)에 대한 오버헤드를 1분으로 가정할 때 10분을 초과하는 RTO가 있습니다. 해당 서버 인스턴스의 성능 문제를 즉시 조사해야 합니다.

        • 표시할 텍스트: RTO 초과함!

  8. 다음 사양을 사용하여 2차 정책 기반 관리 정책을 만듭니다:

    • 일반 페이지:

      • 이름: CustomAvailabilityDatabaseRPO
      • 상태 확인: RPO
      • 대상 대비: IsPrimaryReplica AvailabilityGroup의 모든 DatabaseReplicaState
      • 평가 모드: 일정에 따라
      • 일정: CollectorSchedule_Every_30min
      • 활성화됨: 선택됨
    • 설명 페이지:

      • 범주: 가용성 데이터베이스 경고

      • 설명: 가용성 데이터베이스가 RPO를 1시간 초과했습니다. 가용성 복제본(replica)의 성능 문제를 즉시 조사해야 합니다.

      • 표시할 텍스트: RPO 초과함!

완료되면 각 정책 평가 일정에 대해 하나씩 두 개의 새 SQL Server 에이전트 작업이 만들어집니다. 이러한 작업에는 .로 syspolicy_check_schedule시작하는 이름이 있어야 합니다.

작업 기록을 보고 평가 결과를 검사할 수 있습니다. 평가 오류는 Windows 응용 프로그램(이벤트 뷰어의 경우)에도 이벤트 ID 34052로 기록됩니다. 정책 실패에 대한 경고를 보내기 위해 SQL Server 에이전트를 만들 수도 있습니다. 자세한 내용은 정책 관리자에게 정책 실패를 알리도록 경고 구성을 참조하세요.

성능 문제 해결 시나리오

다음 표에는 일반적인 성능 관련 문제 해결 시나리오가 나와 있습니다.

시나리오 설명
문제 해결: RTO를 초과한 가용성 그룹 데이터 손실 없이 자동 장애 조치(failover) 또는 계획된 수동 장애 조치 후 장애 조치 시간이 복구 목표 시간(RTO)를 초과합니다. 또는 동기 커밋 보조 복제본(예: 자동 장애 조치 파트너)의 장애 조치 시간을 예측할 때, 그것이 RTO를 초과함을 발견할 수 있습니다.
문제 해결: 가용성 그룹의 RPO를 초과함 강제 수동 장애 조치(failover)를 실행한 후 데이터 손실이 RPO보다 많습니다. 또는 비동기 커밋 보조 복제본의 잠재적 데이터 손실을 계산할 때 RPO를 초과한 것을 발견합니다.
문제 해결: 보조 복제본에 반영되지 않은 기본 복제본의 변경 내용 클라이언트 애플리케이션은 주 복제본에 대한 업데이트를 성공적으로 완료하지만 보조 복제본을 쿼리하면 변경 내용이 반영되지 않는 것으로 표시됩니다.

유용한 확장 이벤트

다음 확장 이벤트는 동기화 상태에서 복제본(replica) 문제를 해결할 때 유용합니다.

이벤트 이름 범주 채널 가용성 복제본
redo_caught_up 트랜잭션 디버그 이차적인
redo_worker_entry 트랜잭션 디버그 이차적인
hadr_transport_dump_message alwayson 디버그 기본
hadr_worker_pool_task alwayson 디버그 기본
hadr_dump_primary_progress alwayson 디버그 기본
hadr_dump_log_progress alwayson 디버그 기본
hadr_undo_of_redo_log_scan alwayson 분석 이차적인