次の方法で共有


Always On 可用性グループのパフォーマンスを監視する

適用対象:SQL Server

Always On 可用性グループのパフォーマンス面は、ミッション クリティカルなデータベースに対するサービス レベル アグリーメント (SLA) を維持する上で重要です。 可用性グループがセカンダリ レプリカにログを配布する方法を理解することで、可用性実装の回復時刻の目標 (RTO) および回復ポイントの目標 (RPO) の推定、ならびにパフォーマンスに問題がある可用性グループまたはレプリカにおけるボトルネックの特定が容易になります。 この記事では、同期プロセスについて説明し、主要なメトリックの計算方法を示すと共に、一般的なパフォーマンス トラブルシューティング シナリオへのリンクをいくつか紹介します。

データ同期プロセス

完全に同期するまでの時間を推定し、ボトルネックを特定するには、同期プロセスを理解する必要があります。 パフォーマンスのボトルネックはプロセス内の任意の箇所で発生する可能性があります。ボトルネックの場所を特定することで、基になっている問題をさらに詳しく調べることができます。 次の図と表に、データの同期プロセスを示します。

可用性グループのデータ同期のスクリーンショット。

シーケンス ステップの説明 コメント 有用なメトリック
1 ログの生成 ログ データがディスクにフラッシュされます。 このログはセカンダリ レプリカにレプリケートする必要があります。 ログ レコードによって送信キューが入力されます。 SQL Server: データベース > Log bytes flushed\sec
2 キャプチャ 各データベースのログがキャプチャされ、対応するパートナー キュー (データベース レプリカ ペアごとに 1 つ) に送信されます。 このキャプチャ プロセスは、可用性レプリカが接続されていて、何らかの理由でデータ移動が中断されず、データベース レプリカのペアが [同期中] または [同期中] と表示されている限り、継続的に実行されます。 キャプチャ プロセスがメッセージを適切にスキャンしてエンキューできないと、ログ送信キューがたまります。 SQL Server:可用性レプリカ > レプリカ/秒に送信されたバイト数。これは、その可用性レプリカに対してキューに登録されたすべてのデータベース メッセージの合計の集計です。

プライマリ レプリカの log_send_queue_size (KB) とlog_bytes_send_rate (KB/秒)。
3 送信 各データベース レプリカ キュー内のメッセージはデキューされ、ネットワーク経由でそれぞれのセカンダリ レプリカに送信されます。 SQL Server:可用性レプリカ > トランスポートに送信されたバイト数/秒
4 受信とキャッシュ 各セカンダリ レプリカがメッセージを受信しキャッシュします。 パフォーマンス カウンター SQL Server: 可用性レプリカ > Log Bytes Received/sec
5 書き込み 書き込みのためログがセカンダリ レプリカにフラッシュされます。 ログのフラッシュ後、プライマリ レプリカに受信確認が返送されます。

ログが堅牢化されると、データ損失は回避されます。
パフォーマンス カウンター SQL Server: データベース > Log Bytes Flushed/sec
待機の種類 HADR_LOGCAPTURE_SYNC
6 再実行 フラッシュされたページをセカンダリ レプリカで再実行します。 再実行されるのを待機する間、ページは再実行キューに保持されます。 SQL Server: データベース レプリカ > Redone Bytes/sec

redo_queue_size (KB) と redo_rate
待機の種類 REDO_SYNC

フロー制御ゲート

プライマリ レプリカではフロー制御ゲートを使用して可用性グループが設計されています。このため、すべての可用性レプリカ上でネットワークやメモリ リソースなどのリソースが過剰消費されるのを回避することができます。 これらのフロー制御ゲートは、可用性レプリカの同期正常性状態には影響しませんが、RPO を含む可用性データベースの全体的なパフォーマンスに影響を与える可能性があります。

ログはプライマリ レプリカ上でキャプチャされると、フロー制御の 2 つのレベルの影響を受けるようになります。 いずれかのゲートのメッセージしきい値に達すると、ログ メッセージは特定のレプリカ、または特定のデータベースに送信されなくなります。 送信するメッセージに対して確認応答メッセージが受信され、結果として送信メッセージの数がしきい値を下回ると、メッセージを送信できるようになります。

フロー制御ゲートに加えて、ログ メッセージの送信を妨げる可能性があるもう 1 つの要因があります。 レプリカを同期すると、メッセージは確実にログ シーケンス番号 (LSN) の順序で送信および適用されます。 ログ メッセージが送信される前に、その LSN は、受信確認済みの最小の LSN 番号に対してチェックを行い、しきい値の 1 つ未満であることを確認します (メッセージの種類によって異なります)。 2 つの 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

2 つの有用なパフォーマンス カウンターである SQL Server: 可用性レプリカ > Flow control/secSQL Server: 可用性レプリカ > Flow Control Time (ms/sec) では、最後の 1 秒以内に、フロー制御がアクティブになった回数とフロー制御を待機していた時間を示します。 フロー制御の待機時間が長いと、RPO が大きくなります。 フロー制御の待機時間が長くなる可能性がある問題の種類の詳細については、「 トラブルシューティング: 非同期コミット可用性グループ レプリカによるデータ損失の可能性」を参照してください。

フェールオーバー時間の見積もり (RTO)

SLA での RTO は、特定の時点での Always On 実装のフェールオーバー時間に依存し、次の数式で表すことができます。

可用性グループの RTO 計算のスクリーンショット。

重要

可用性グループに複数の可用性データベースが含まれている場合、Tfailover が最も高い可用性データベースは RTO 準拠の制限値になります。

障害検出時間 Tdetection は、システムが障害を検出するのにかかる時間です。 この時間は、個々の可用性レプリカではなく、クラスター レベルの設定に依存します。 構成されている自動フェールオーバーの条件に応じて、SQL Server での重大な内部エラー (孤立したスピンロックなど) への瞬時の応答として、フェールオーバーをトリガーすることができます。 この場合、 sp_server_diagnostics エラー レポート が Windows Server フェールオーバー クラスター (WSFC) に送信されるのと同じ速度で検出できます。 既定の間隔は、正常性チェックタイムアウトの 1/3 です。クラスターの正常性チェックのタイムアウト (既定では 30 秒) が切れているか、リソース DLL と SQL Server インスタンスの間のリースの有効期限が切れている (既定では 20 秒) など、タイムアウトが原因でフェールオーバーをトリガーすることもできます。 この場合、検出時間はタイムアウト間隔と同じ長さになります。 詳細については、「可用性グループの自動フェールオーバーのための柔軟なフェールオーバー ポリシー (SQL Server)」を参照してください。

フェールオーバー可能な状態にするためにセカンダリ レプリカで行う必要があるのは、ログの末尾まで再実行することだけです。 再実行時間 Tredo は次の式を使用して計算します。

可用性グループの再実行時間の計算のスクリーンショット。

ここで、redo_queueredo_queue_size 内の値であり、redo_rateredo_rate 内の値です。

フェールオーバーのオーバーヘッド時間 Toverhead には、WSFC クラスターをフェールオーバーしてデータベースをオンラインにするのにかかる時間が含まれます。 この時間は通常は短く一定です。

潜在的なデータ損失の評価 (RPO)

SLA での RPO は、特定の時点での Always On 実装のデータ損失の可能性に依存します。 このデータ損失の可能性は次の式で表すことができます。

可用性グループの RPO 計算のスクリーンショット。

ここで、log_send_queue は、log_send_queue_size の値であり、"ログ生成速度" は、> の値です。

警告

可用性グループに 1 つ以上の可用性データベースが含まれている場合、最高 Tdata_loss で可用性データベースの RPO 対応制限値になります。

ログ送信キューは、重大なエラーによって失われる可能性のあるすべてのデータを表します。 一見すると、ログの送信レートではなくログ生成率が使用されているのが興味深い点です ( log_send_rateを参照)。 ただし、ログ送信レートを使用すると同期する時間しか得られないことに注意してください。一方、RPO では、データ損失は、同期の速度ではなく、生成された速度に基づいて測定されます。

Tdata_loss を推定するには、last_commit_time を使用する方法が簡単です。 プライマリ レプリカ上の DMV は、この値をすべてのレプリカにレポートします。 プライマリ レプリカの値とセカンダリ レプリカの値との差を計算することで、セカンダリ レプリカ上のログがプライマリ レプリカに追いつく速さを推定することができます。 前述のように、この計算では、ログの生成速度に基づいてデータ損失が発生する可能性は示されませんが、近似値にする必要があります。

SSMS ダッシュボードを使用して RTO と RPO を見積もる

Always On 可用性グループでは、RTO と RPO が計算され、セカンダリ レプリカでホストされているデータベースに対して表示されます。 SQL Server Management Stuiod (SSMS) ダッシュボードのプライマリ レプリカでは、RTO と RPO がセカンダリ レプリカによってグループ化されます。

ダッシュボード内で RTO と RPO を表示するには、次の手順を実行します。

  1. SQL Server Management Studio で、Always On 高可用性 ノードを展開し、可用性グループの名前を右クリックして [ダッシュボードの表示] を選択します。

  2. [グループ化] タブで、 [列の追加と削除] を選択します。 [推定復旧時間 (秒)] (RTO) と [推定データ損失 (時間)] (RPO) の両方のチェック ボックスをオンにします。

    RTO RPO ダッシュボードを示すスクリーンショット。

セカンダリ データベースの RTO の計算

フェールオーバーが発生した後、セカンダリ データベース の復旧に必要な時間は、復旧時間の計算で決まります。 フェールオーバー時間は通常は短く一定です。 この検出時間は、個々の可用性レプリカではなく、クラスター レベルの設定に依存します。

セカンダリ データベース (DB_sec) の場合、RTO の計算と表示は、その redo_queue_sizeredo_rateに基づいています。

RTO の計算のスクリーンショット。

まれなケースを除き、セカンダリ データベースの RTO を計算する数式は次のようになります。

RTO を計算する数式のスクリーンショット。

セカンダリ データベースの RPO の計算

セカンダリ データベース (DB_sec) の場合、RPO の計算と表示は、 is_failover_readylast_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 は、セカンダリ データベースでも正常に書き込まれたプライマリ データベースからのトランザクションの最新のコミット時間です。 この数は、プライマリ データベースとセカンダリ データベースの両方で同じです。 ただし、これら 2 つの値の間のギャップは、保留中のトランザクションがセカンダリ データベースで強化されておらず、フェールオーバーが発生した場合に失われる可能性がある期間です。

RPO の計算のスクリーンショット。

RTO/RPO 数式で使用されるパフォーマンス メトリック

  • redo_queue_size (KB): RTO で使用される再実行キューのサイズは、 last_received_lsnlast_redone_lsnの間のトランザクション ログのサイズです。 last_received_lsn値は、このセカンダリ データベースをホストするセカンダリ レプリカによってすべてのログ ブロックが受信されたポイントを識別するログ ブロック ID です。 last_redone_lsnの値は、セカンダリ データベースで再実行された最後のログ レコードのログ シーケンス番号です。 これら 2 つの値に基づいて、開始ログ ブロック (last_received_lsn) と終了ログ ブロック (last_redone_lsn) の ID を確認できます。 これら 2 つのログ ブロック間の領域は、まだ再実行されていないトランザクション ログ ブロックの数を表すことができます。 これはキロバイト (KB) で測定されます。

  • redo_rate (KB/秒): RTO 計算で使用される累積値は、1 秒あたりにセカンダリ データベースで再実行または再生されたトランザクション ログ (KB) の量を示します。

  • last_commit_time (datetime): RPO で使用されるこの値は、プライマリ データベースとセカンダリ データベース間で異なる意味を持ちます。 プライマリ データベースの場合、 last_commit_time は最新のトランザクションがコミットされた時刻です。 セカンダリ データベースの場合、 last_commit_time は、セカンダリ データベースでも正常に書き込まれたプライマリ データベース上のトランザクションの最新のコミットです。 セカンダリのこの値はプライマリの同じ値と同期する必要があるため、これら 2 つの値の間の差はデータ損失の推定値 (RPO) となります。

DMV を使用して RTO と RPO を推定する

データベースの RPO と RTO を見積もるために、 SYS.DM_HADR_DATABASE_REPLICA_STATES および sys.dm_hadr_database_replica_cluster_states の DMV に対してクエリを実行できます。 以下のクエリでは、両方に実行するストアド プロシージャが作成されます。

注意

必ず、最初に 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. 出力には、ターゲット セカンダリ レプリカ データベースの RTO の値が表示されます。 RPO 推定ストアド プロシージャで使用する group_idreplica_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. ターゲットのセカンダリ データベースのgroup_idreplica_id、およびgroup_database_idを使用してproc_calculate_RPOを実行します。

    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. 出力には、ターゲット セカンダリ レプリカ データベースの RPO の値が表示されます。

RTO と RPO の監視

このセクションでは、可用性グループの RTO および RPO メトリックを監視する方法を実演します。 この実演の内容は、「The Always On health model, part 2: Extending the health model」 (Always On 正常性モデル、パート 2: 正常性モデルの拡張) で提供している GUI のチュートリアルに類似しています。

フェールオーバー時間の 見積もり (RTO) と潜在的なデータ損失 (RPO) の推定におけるフェールオーバー時間潜在的なデータ損失 の計算の要素は、ポリシー管理ファセット データベース レプリカ状態のパフォーマンス メトリックとして便利に提供されます。 詳細については、「 SQL Server オブジェクトのポリシー ベースの管理ファセットを表示する」を参照してください。 この 2 つのメトリックはスケジュールに従って監視することができます。メトリックが指定の RTO および RPO を超えた場合はそれぞれアラートが返されます。

デモ スクリプトでは、以下の特性を備え、それぞれのスケジュールに従って実行される 2 つのシステム ポリシーが作成されます。

  • RTO ポリシーは 5 分ごとに評価され、推定フェールオーバー時間が 10 分を超えると失敗します。

  • RPO ポリシーは 30 分ごとに評価され、推定データ損失が 1 時間を超えると失敗します。

  • 2 つのポリシーの構成は、すべての可用性レプリカ上で同じです。

  • ポリシーはすべてのサーバー上で評価されますが、可用性グループ上ではローカルの可用性レプリカがプライマリ レプリカである場合にのみ評価されます。 ローカル可用性レプリカがプライマリ レプリカでない場合、ポリシーは評価されません。

  • プライマリ レプリカ上で Always On ダッシュボードを表示すると、ポリシー エラーを容易に確認できます。

ポリシーを作成するには、可用性グループに参加するすべてのサーバー インスタンスで次の手順に従います。

  1. SQL Server エージェント サービスがまだ開始 されていない場合は開始します。

  2. SQL Server Management Studio の [ツール] メニューの [オプション] 選択します。

  3. [SQL Server Always On] タブで、[ユーザー定義の Always On ポリシーを有効にする] を選択し、[OK] を選択します

    この設定により、適切に構成されたカスタム ポリシーを Always On ダッシュボードに表示できるようになります。

  4. 次の仕様に基づいてポリシー ベースの管理条件を作成します。

    • 名前: RTO
    • ファセット: データベース レプリカ状態
    • フィールド: Add(@EstimatedRecoveryTime, 60)
    • 演算子: <=
    • : 600

    この状態は、フェールオーバーの可能性がある時間が 10 分を超えると失敗します。これには、障害検出とフェールオーバーの両方に対する 60 秒のオーバーヘッドが含まれます。

  5. 次の仕様に基づいて 2 番目のポリシー ベースの管理条件を作成します。

    • 名前: RPO
    • ファセット: データベース レプリカ状態
    • フィールド: @EstimatedDataLoss
    • 演算子: <=
    • : 3600

    この条件は、データ損失の可能性が 1 時間を超えると失敗します。

  6. 次の仕様に基づいて 3 番目のポリシー ベースの管理条件を作成します。

    • 名前: IsPrimaryReplica
    • ファセット: 可用性グループ
    • フィールド: @LocalReplicaRole
    • 演算子: =
    • : Primary

    この条件では、特定の可用性グループのローカルの可用性レプリカがプライマリ レプリカであるかどうかがチェックされます。

  7. 次の仕様に基づいてポリシー ベースの管理ポリシーを作成します。

    • [全般] ページ:

      • 名前: CustomSecondaryDatabaseRTO

      • 条件の確認: RTO

      • 対象: IsPrimaryReplica AvailabilityGroupすべての DatabaseReplicaState

        この設定により、ポリシーは必ず、ローカルの可用性レプリカがプライマリ レプリカである可用性グループのみで評価されます。

        • [評価モード] :スケジュールで実行

        • スケジュール: CollectorSchedule_Every_5min

        • 有効: 選択

    • [説明] ページ:

      • カテゴリ:可用性データベースの警告

        この設定により、Always On ダッシュボードにポリシーの評価結果を表示できるようになります。

        • 説明:検出とフェールオーバーのオーバーヘッドが 1 分であると仮定すると、現在のレプリカの RTO は 10 分を超えています。すぐに、それぞれのサーバー インスタンスでのパフォーマンスの問題を調査する必要があります。

        • 表示するテキスト:RTO を超過しました!

  8. 次の仕様に基づいて 2 番目のポリシー ベースの管理ポリシーを作成します。

    • [全般] ページ:

      • 名前: CustomAvailabilityDatabaseRPO
      • 条件の確認: RPO
      • 対象: IsPrimaryReplica AvailabilityGroupすべての DatabaseReplicaState
      • [評価モード] :スケジュールで実行
      • スケジュール: CollectorSchedule_Every_30min
      • 有効: 選択
    • [説明] ページ:

      • カテゴリ:可用性データベースの警告

      • 説明:可用性データベースは、1 時間の RPO を超過しています。すぐに、可用性レプリカでのパフォーマンスの問題を調査する必要があります。

      • 表示するテキスト:RPO を超過しました!

完了すると、ポリシー評価スケジュールごとに 1 つずつ、2 つの新しい SQL Server エージェント ジョブが作成されます。 これらのジョブには、 syspolicy_check_scheduleで始まる名前が必要です。

評価結果を確認するために、ジョブ履歴を表示できます。 評価エラーは、イベント ID 34052 で Windows アプリケーション ログ (イベント ビューアー内) にも記録されます。 また、ポリシー エラー発生時にアラートを送信するように SQL Server エージェントを構成することもできます。 詳細については、「 ポリシー管理者にポリシーエラーを通知するようにアラートを構成する」を参照してください。

パフォーマンスのトラブルシューティング シナリオ

次の表に、一般的なパフォーマンスに関連するトラブルシューティング シナリオを示します。

シナリオ 説明
トラブルシューティング: 可用性グループ接続の超過 RTO データ損失のない自動フェールオーバーまたは計画的な手動フェールオーバーの後で、フェールオーバー時間が RTO を超過します。 または、同期コミット セカンダリ レプリカのフェールオーバー時間を推定したとき (自動フェールオーバー パートナーなど)、RTO を超過していることが判明します。
トラブルシューティング: 可用性グループが RPO を超えた 強制的な手動フェールオーバーを実行した後で、データ損失が RPO より大きくなります。 または、非同期コミット セカンダリ レプリカのデータ損失の可能性を計算したとき、計算結果が RPO を超過していることが判明します。
トラブルシューティング:プライマリ上の変更がセカンダリ レプリカに反映されない クライアント アプリケーションはプライマリ レプリカの更新を正常に完了しますが、セカンダリ レプリカに対してクエリを実行すると、変更が反映されていないことが示されます。

有用な拡張イベント

同期中の状態にあるレプリカのトラブルシューティングを行う場合は、次の拡張イベントは便利です。

イベント名 カテゴリ チャネル 可用性レプリカ
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 分析 セカンダリ