次の方法で共有


トランザクション レプリケーションのパフォーマンスの向上

適用対象: SQL Server Azure SQL Managed Instance

レプリケーションの全般的パフォーマンスの向上」で説明した全般的なパフォーマンス向上のヒントを検討した後、トランザクション レプリケーションに固有なこれらの項目を併せて検討してください。

データベースの設計

  • アプリケーションの設計で、トランザクションのサイズを最小化する。

    既定では、トランザクション レプリケーションはトランザクションの境界に従って変更を反映させます。 トランザクションが小さくなると、ネットワークの問題によりディストリビューション エージェントがトランザクションを再送信する可能性は低くなります。 エージェントがトランザクションを再送信する必要があっても、送信されるデータは少なくなります。

ディストリビューターの構成

  • ディストリビューション専用サーバーを構成する。

    リモート ディストリビューターを構成することにより、パブリッシャーの処理オーバーヘッドを減らすことができます。 詳しくは、「 Configure Distribution」を参照してください。

  • ディストリビューション データベースのサイズを適切に設定する。

    システムの典型的な負荷でレプリケーションをテストし、コマンドを格納するために必要な領域を決定します。 データベースが頻繁に自動拡張しなくてもコマンドを格納できるだけの大きさを備えていることを確認します。 データベースのサイズの変更に関する詳細については、「ALTER DATABASE (Transact-SQL)」を参照してください。

パブリケーションの設計

  • パブリッシュされたテーブルに対してバッチ更新を行う場合は、ストアド プロシージャの実行をレプリケートする。

    バッチ更新がサブスクライバーで多数の行に影響することがある場合には、パブリッシュされたテーブルをストアド プロシージャで更新することを検討して、ストアド プロシージャの実行をパブリッシュしてください。 ディストリビューション エージェントは、影響を受けたすべての列に対する更新または削除を送信するのではなく、サブスクライバーで同じパラメーター値を使用して同じプロシージャを実行します。 詳細については、「トランザクション レプリケーションにおけるパブリッシング ストアド プロシージャの実行」をご覧ください。

  • 複数のパブリケーションにアーティクルを分散する。

    -SubscriptionStreams パラメーターを使用できない場合は、複数のパブリケーションを作成することを検討してください。 これらのパブリケーションにアーティクルを分散させると、サブスクライバーに対する変更をレプリケーションで並列的に適用できます。

サブスクリプションに関する注意点

  • 同一のパブリッシャーに複数のパブリケーションがある場合は、共有エージェントの代わりに独立エージェントを使用する (これはパブリケーションの新規作成ウィザードの既定の設定です)。

  • エージェントを連続して実行し、高い頻度のスケジュールにはしない。

    エージェントを連続的に実行するようにし、高い頻度のスケジュール、たとえば毎分などのスケジュールの作成を避けることで、レプリケーションのパフォーマンスが向上します。これは、エージェントが開始および停止する必要がなくなるからです。 ディストリビューション エージェントを連続的に実行するように設定すると、トポロジ内で接続しているその他のサーバーに、短い待機時間で変更が反映されます。 詳細については、以下を参照してください:

ディストリビューション エージェントおよびログ リーダー エージェントのパラメーター

トラフィックが多い OLTP システムでは、ログ リーダーとディストリビューション エージェントのスループットを増やすため、エージェント プロファイルのパラメーターが調節されることがよくあります。

ログ リーダーとディストリビューション エージェントのパフォーマンスを向上させるために最適な値を確認するテストが実施されました。 このテストの結論は、どのような状況にどのような値が適しているかはワークロードによって決まるため、すべての状況でパフォーマンスが向上するような 1 つの値の調整はありません。

次のことがわかりました。

  • ワークロードが比較的小さいトランザクション (500 コマンド未満) である "ログ リーダー エージェント" では、ReadBatchSize の値を高くするとスループットが向上する可能性があります。 ただし、大きいトランザクションのワークロードでは、この値を変更してもパフォーマンスは向上しません。
    • 複数のログ リーダー エージェントと複数のディストリビューション エージェントが同じサーバーで並列実行している場合は、ReadBatchSize の値を高くすると、ディストリビューション データベースで競合が発生します。
  • "ディストリビューション エージェント" の場合
    • CommitBatchSize の値を大きくすると、スループットが向上することがあります。 欠点は、障害が発生した場合、ディストリビューション エージェントがロールバックして最初からやり直し、多数のトランザクションを再適用する必要があることです。
    • SubscriptionStreams の値を大きくすると、サブスクライバーへの複数の接続が変更のバッチを並列で適用するため、ディストリビューション エージェントの全体的なスループットの向上に役立ちます。 ただし、プロセッサの数および他のメタデータの条件 (主キー、外部キー、一意制約、インデックスなど) によっては、SubscriptionStreams の値を高くすると悪影響がある可能性があります。 さらに、ストリームの実行またはコミットが失敗した場合、ディストリビューション エージェントはフォールバックし、単一のストリームで失敗したバッチを再試行します。

このテストについて詳しくは、ブログ「レプリケーションエージェントのプロファイルパラメータを最適化してパフォーマンスを向上させる」(パフォーマンス向上のためのレプリケーション エージェントのプロファイル パラメーターの最適化) をご覧ください。

ログ リーダー エージェント (Log Reader Agent)

ReadBatchSize

  • ログ リーダー エージェントの -ReadBatchSize パラメーターの値を大きくする。

ログ リーダー エージェントとディストリビューション エージェントは、トランザクションの読み取りとコミット操作のバッチ サイズをサポートしています。 バッチ サイズの既定値は 500 トランザクションです。 ログ リーダー エージェントは、レプリケーション用にマークが付けられているかどうかにかかわらず、一定の数のトランザクションをログから読み取ります。 多数のトランザクションがパブリケーション データベースに書き込まれているが、その中のごくわずかなサブセットだけにレプリケーションのマークが付いている場合、-ReadBatchSize パラメーターでログ リーダー エージェントの読み取りバッチ サイズを増やす必要があります。 このパラメーターは、Oracle パブリッシャーには適用されません。

  • 小さいトランザクション (500 コマンド未満) のワークロードでは、ReadBatchSize を大きくすると (最大 5000)、1 秒間に処理されるコマンドの数が増えます。
  • 大きいワークロード (500 ~ 1000 コマンドのトランザクション) では、ReadBatchSize を大きくしてもパフォーマンスはあまり向上しません。 ReadBatchSize を大きくすると、1 回のラウンドトリップでディストリビューション データベースに書き込まれるトランザクションの数が増えます。 これにより、トランザクションとコマンドがディストリビューション エージェントによって処理される時間が長くなり、レプリケーション処理の待ち時間が増えます。

PollingInterval

  • ログ リーダー エージェントの -PollingInterval パラメーターの値を小さくする。

-PollingInterval パラメーターは、トランザクションをレプリケートするために、パブリッシュされたデータベースのトランザクション ログをクエリする頻度を指定します。 既定値は 5 秒です。 この値を小さくすると、ログを呼び出す頻度は高くなります。これにより、パブリケーション データベースからディストリビューション データベースへのトランザクションの配信の待機時間を減らすことができます。 しかし、待機時間を減らす必要性と、照会の頻度が高くなることによるサーバーの負荷の増加とのバランスをとる必要があります。

MaxCmdsInTran

  • 予期せずに 1 回だけ発生するボトルネックを解決するには、ログ リーダー エージェントに対して –MaxCmdsInTran パラメーターを使用します。

–MaxCmdsInTran パラメーターは、ログ リーダーがディストリビューション データベースにコマンドを書き込む際に、トランザクションにグループ化されるステートメントの最大数を指定します。 このパラメーターを使用すると、ログ リーダー エージェントおよびディストリビューション エージェントは、サブスクライバーでコマンドを適用するときに、パブリッシャーで (多数のコマンドで構成される) 大きなトランザクションを複数の小さなトランザクションに分割できます。 このパラメーターを指定すると、ディストリビューターでの競合を減らし、パブリッシャーとサブスクライバーの間の待機時間を減らすことができます。 元のトランザクションはより小さな単位で適用されるため、サブスクライバーは元のトランザクションが終了する前に、大きな論理パブリッシャー トランザクションの行にアクセスし、トランザクションの厳密な原子性を損なうことがあります。 既定値は 0です。この場合、パブリッシャーのトランザクション境界が保護されます。 このパラメーターは、Oracle パブリッシャーには適用されません。

警告

MaxCmdsInTran は、常に有効になるようには設計されていませんでした。 このパラメーターは、ユーザーが誤って 1 つのトランザクションで多数の DML 操作を実行した場合に対応するためのものです (このような場合、トランザクション全体がディストリビューション データベースに格納されるまでコマンドの配布で遅延が発生したり、ロックが保持されたりするなどの問題が発生します)。 このような状況が定期的に発生する場合は、アプリケーションを確認して、トランザクションのサイズを縮小する方法を見つけます。

警告

Change Data Capture とレプリケーションの両方で特定のパブリケーション データベースが有効になっている場合、MaxCmdsInTran はサポートされません。 この構成で MaxCmdsInTran を使用すると、CDC 変更テーブルでデータが失われる可能性があります。 また、大規模なトランザクションのレプリケーション中に MaxCmdsInTran パラメーターを追加および削除すると、PK エラーが発生する可能性があります。

ディストリビューション エージェント

SubscriptionStreams

  • ディストリビューション エージェントの –SubscriptionStreams パラメーターを大きくする。

–SubscriptionStreams パラメーターを使用すると、集計レプリケーションのスループットを大幅に向上できます。 このパラメーターを使用すると、単一のスレッドを使用するときに存在するトランザクション特性の多くを維持しつつ、変更のバッチをサブスクライバーへの複数の接続で並列的に適用できます。 いずれかの接続が実行またはコミットに失敗した場合、進行中のバッチがすべての接続について中止されます。その場合、エージェントは、単一のストリームを使用して、失敗したバッチを再試行します。 この再試行フェーズが完了するまでは、サブスクライバー側に、トランザクションの一時的な不整合が存在する可能性があります。 サブスクライバーのトランザクション一貫性は、前回失敗したバッチが正常にコミットされた後で復元されます。

このエージェント パラメーターの値は、sp_addsubscription (Transact-SQL)@subscriptionstreams を使用して指定できます。

ブロッキング モニター スレッド

ディストリビューション エージェントでは、セッション間のブロックを検出するブロッキング モニター スレッドを保持します。 ブロッキング モニター スレッドでセッション間のブロックを検出した場合、ディストリビューション エージェントではセッションを 1 つ使用するように切り替え、以前に適用できなかったコマンドの現在のバッチを再適用します。

ブロッキング モニター スレッドでは、ディストリビューション エージェント セッション間のブロックを検出できます。 ただし、ブロッキング モニター スレッドでは、次の状況でブロックを検出することはできません。

  • ブロックが発生するいずれかのセッションがディストリビューション エージェント セッションではない
  • セッションのデッドロックによってディストリビューション エージェントのアクティビティがフリーズする

このような状況では、コマンドが実行されるとすぐに、ディストリビューション エージェントによってすべてのセッションが一緒にコミットされるように調整されます。 次の条件を満たす場合、セッション間のデッドロックが発生します。

  • ディストリビューション エージェント セッションとディストリビューション エージェント セッションではないセッションの間でブロックが発生する場合
  • ディストリビューション エージェントで、ディストリビューション エージェントによってすべてのセッションが一緒にコミットされるように調整する前に、すべてのセッションでコマンドの実行が完了するのを待機している場合

たとえば、SubscriptionStreams パラメーターを 8 に設定します。 セッション 10 からセッション 17 は、ディストリビューション エージェント セッションです。 セッション 18 はディストリビューション エージェント セッションではありません。 セッション 10 はセッション 18 によってブロックされ、セッション 18 はセッション 11 によってブロックされます。 さらに、セッション 10 およびセッション 11 は一緒にコミットされる必要があります。 しかし、ブロックされるため、ディストリビューション エージェントでセッション 10 およびセッション 11 を一緒にコミットすることはできません。 そのため、ディストリビューション エージェントでは、セッション 10 とセッション 11 がコマンドの実行を完了するまで、これら 8 個のセッションを一緒にコミットするように調整することはできません。

この例では、コマンドを実行しているセッションがない状態になります。 QueryTimeout プロパティで指定された時刻に到達すると、ディストリビューション エージェントによってすべてのセッションがキャンセルされます。

Note

QueryTimeout プロパティの既定値は 5 分です。

このクエリのタイムアウト期間中にディストリビューション エージェントのパフォーマンス カウンターから次の傾向を通知される可能性があります。

  • Dist: Delivered Cmds/sec パフォーマンス カウンターの値は、常に 0 です。
  • Dist: Delivered Trans/sec パフォーマンス カウンターの値は、常に 0 です。
  • Dist: Delivery Latency パフォーマンス カウンターにより、スレッドのデッドロックが解決されるまで、値の増加が報告されます。

SQL Server オンライン ブックの "ディストリビューション エージェントのレプリケーション" トピックには、SubscriptionStreams パラメーターに関する次の説明 ("いずれかの接続を実行またはコミットできない場合、すべての接続で現在のバッチが中止され、エージェントでは単一ストリームを使用して失敗したバッチを再試行します") が含まれます。

ディストリビューション エージェントで単一セッションを使用して、適用できなかったバッチを再試行されます。 ディストリビューション エージェントで正常にバッチを適用した後、ディストリビューション エージェントでは再試行することなく、複数のセッションの使用が再開されます。

CommitBatchSize

  • ディストリビューション エージェントの -CommitBatchSize パラメーターの値を大きくする。

一連のトランザクションをコミットすると、一定のオーバーヘッドが生じます。より多くのトランザクションを、より低い頻度でコミットするほど、オーバーヘッドは多くのデータに分散されます。 CommitBatchSize を増やすと (最大 200)、サブスクライバーにコミットされるトランザクションが増えるので、パフォーマンスが向上する可能性があります。 しかし、変更を適用するコストは、ログを含むディスクの最大 I/O などのその他の要因によって制限されるため、このパラメーターを大きくする利点は少なくなります。 さらに、検討すべきトレード オフもあります。ディストリビューション エージェントのやり直しの原因となる失敗をすべてロールバックし、多くのトランザクションを再適用する必要があります。 信頼性の低いネットワークでは、値を小さくすると失敗が少なくなり、失敗が発生した場合にロールバックおよび再適用するトランザクションの数が減ります。