キュー更新における競合の検出と解決
キュー更新サブスクリプションによって複数の場所にある同じデータを変更できるため、パブリッシャでデータを同期するときに競合が起こる可能性があります。レプリケーションによって、パブリッシャとデータの変更を同期するときに競合を検出し、パブリケーションを作成したときに選択した解決方法でこれらの競合を解決します。発生する可能性がある競合は、次のとおりです。
更新および挿入競合。この競合は、同一のデータが 2 つの異なる場所で変更された場合に発生します。一方の変更が競合の優先データとなり、他方は非優先データとなります。
削除競合。この競合は、同一行が、ある箇所で削除され、別の箇所で変更された場合に発生します。
競合の検出と解決は、時間とリソースの消費が大きいプロセスであるため、複数のサブスクライバがそれぞれ異なるデータのサブセットを変更できるようにデータ パーティションを作成して、アプリケーションの競合を最小限に抑えるようにします。
競合の検出
パブリケーションを作成してキュー更新を有効にすると、newid() を既定値とする uniqueidentifier 列 (msrepl_tran_version) が、レプリケーションによって作成元のテーブルに追加されます。パブリッシュされたデータがパブリッシャまたはサブスクライバで変更されると、行は新しいグローバルな一意識別子 (GUID) を受け取り、新しい行が存在することを示します。キュー リーダー エージェントは同期のとき、この列を使って競合の有無を確認します。
キューに登録されたトランザクションは、行の古い値と新しい値を保持しています。トランザクションがパブリッシャに適用されると、トランザクションの GUID とパブリケーションの GUID が比較されます。トランザクションの古い GUID がパブリケーションの GUID と一致した場合は、パブリケーションは更新され、行にはサブスクライバで作成された新しい GUID が割り当てられます。トランザクションの GUID でパブリケーションを更新すると、パブリケーションとトランザクションの間で一致する行が得られます。
トランザクションの古い GUID がパブリケーションの GUID と一致しない場合は、競合が検出されます。パブリケーションの新しい GUID は、異なる 2 つの行のバージョンが存在することを示します。1 つはサブスクライバが送信するトランザクションの行で、もう 1 つはパブリッシャの新しい行です。この場合、このサブスクライバのトランザクションを同期する前に、他のサブスクライバまたはパブリッシャがパブリケーション内の同一の行を更新しています。
マージ レプリケーションの場合とは違って、GUID 列を使用するのは行を識別するためでなく、行に変更があったかどうかを調べるためです。
競合の解決
キュー更新を使用してパブリケーションを作成するときは、競合が検出された場合に使用する競合回避モジュールを選択します。競合回避モジュールでは、同期中に同じ行の複数のバージョンが検出された場合に、キュー リーダー エージェントで処理する方法を指定します。パブリケーションにサブスクリプションがなければ、パブリケーションの作成後に競合解決方法を変更できます。使用可能な競合解決方法は次のとおりです。
パブリッシャ優先 (既定値)
パブリッシャ優先およびサブスクリプション再初期化
サブスクライバ優先
競合は記録され、競合表示モジュールによって表示可能です。
キュー更新の競合解決方法を設定するには
SQL Server Management Studio: キュー更新の競合解決オプションを設定する方法 (SQL Server Management Studio)
レプリケーション Transact-SQL プログラミング : トランザクション パブリケーションに対するサブスクリプションの更新を有効にする方法 (レプリケーション Transact-SQL プログラミング)
データの競合を表示するには
- SQL Server Management Studio: トランザクション パブリケーションのデータの競合を表示する方法 (SQL Server Management Studio)
パブリッシャ優先
競合解決方法がパブリッシャ優先の場合は、トランザクションの一貫性はパブリッシャのデータに基づいて維持されます。競合を起こしたトランザクションは、それを開始したサブスクライバにロールバックされます。
キュー リーダー エージェントが競合を検出すると、補正コマンドが生成されます。補正コマンドをディストリビューション データベースに通知することで、このコマンドはサブスクライバへ反映されます。その後、ディストリビューション エージェントは、競合状態のトランザクションを発信したサブスクライバに補正コマンドを適用します。補正アクションによって、パブリッシャの行に一致するようにサブスクライバの行が更新されます。
補正コマンドが適用されるまでは、サブスクライバにロールバックされるトランザクションの結果を読み取ることができます。この処理は、ダーティ リード ("READ UNCOMMITTED" 分離レベル) と同じです。後で発生する従属トランザクションは補正されません。ただし、トランザクション境界は受け入れられます。そして、トランザクション内のすべてのアクションがコミットされます。競合の場合はロールバックされます。
パブリッシャ優先およびサブスクリプション再初期化
競合を解決するためにサブスクライバを再初期化すると、サブスクライバのトランザクション一貫性が最も高くなります。ただし、パブリケーションのデータ量が多い場合、この再初期化には時間がかかります。
キュー リーダー エージェントが競合を検出すると、キューに登録された残りのトランザクション (競合状態のトランザクションも含む) は拒否され、サブスクライバには再初期化のマークが付けられます。パブリケーションに対して次に作成されるスナップショットは、ディストリビューション エージェントによってサブスクライバに適用されます。
サブスクライバ優先
サブスクライバ優先の方法による競合の検出は、パブリッシャ優先を更新した前回のサブスクライバ トランザクションを意味します。この場合、競合が検出されても、サブスクライバによって送信されたトランザクションは引き続き使用され、パブリッシャが更新されます。そのような変更によってもデータの整合性が失われない場合には、サブスクライバ優先の方法が適しています。