SQL Serverが別の世代バッチで子世代と親世代を処理する場合の非収束
この記事では、子世代と親世代を別々の世代バッチで処理SQL Server場合に発生する非収束の問題を解決するのに役立ちます。
元の製品バージョン: SQL Server
元の KB 番号: 308266
現象
サブスクライバーの子テーブルへの INSERT コマンドの損失は、次の条件で発生する可能性があります。
- マージ レプリケーション トポロジは、パブリッシャー、1 つ以上のリパブリッシャー、1 つ以上のサブスクライバーを持つ階層型です。
- マージ レプリケーション パブリケーションには、1 つ以上の親アーティクルと子アーティクルが存在し、その間に結合フィルターが定義されています。
-
NOT FOR REPLICATION
これら 2 つのアーティクル間のリレーションシップに対して、リパブリッシュとサブスクライバーに外部キー制約が存在します。 - 子アーティクルへの INSERT は、マージ エージェント パラメーターで指定された値を超える、関連付けられている親の世代とは別の世代で
-DownloadGenerationsPerBatch
発生します。 そのため、マージ エージェントは、関連付けられている親世代とは別の世代のバッチで子の生成を処理します。 - パブリッシャーと再発行の間、および子と親の生成バッチの処理の間で、マージ処理が中断されます。
回避策
マージ レプリケーション アーキテクチャでは、世代のバッチ境界を越えて親子の変更を一緒に保つメカニズムは提供されません。 この問題を回避するには、次のいずれかを実行します。
-
-UploadGenerationsPerBatch
パラメーターと-DownloadGenerationsPerBatch
マージ エージェント パラメーターを最大値の 2000 に増やします。これにより、親アーティクルの世代とは別のバッチで子アーティクルの生成を処理する可能性が実質的に排除されます。
または
- 再発行時
NOT FOR REPLICATION
に外部キー制約の プロパティを削除します。 この場合、関連付けられている親アーティクル行がないため、マージ エージェントは子アーティクルに行を挿入できません。 ただし、この変更に関連してパフォーマンスが低下する可能性があることに注意してください。 マージ エージェントでこれらの子行を挿入できない場合は、それらの変更を再試行する必要があります。 マージ エージェント再試行プロセスは、通常のバッチ処理モードよりもはるかに効率的ではありません。
詳細
この問題が発生する可能性があるイベントのより詳細なシーケンスを次に示します。 パラメーターと -DownloadGenerationsPerBatch
マージ エージェント パラメーター (この問題に大きく影響する) の既定値-UploadGenerationsPerBatch
は 100 です。 次の例では、 パラメーターと パラメーターが変更されていないと-DownloadGenerationsPerBatch
します-UploadGenerationsPerBatch
。
- INSERT は、最上位の発行元から子と親のアーティクルに対して発生します。 子アーティクルは、別のテーブルに対する外部キー制約を持つパブリケーション内の任意のアーティクルであり、親アーティクルと呼ばれます。 これら 2 つのアーティクルはマージ レプリケーション参加フィルターによって関連しており、リパブリックとサブスクライバーの実際のサーバー側外部キー制約は NOT FOR REPLICATION プロパティでマークされます。 テーブルで sp_help ストアド プロシージャを実行して、制約がレプリケーション用でないかどうかを判断できます (不明な場合)。
- 子テーブルへの INSERT は、ジェネレーション 110 で発生します (たとえば)。 親テーブルへの INSERT は、第 250 世代で発生します (たとえば)。 これらの世代間の分離は、パラメーターよりも
-DownloadGenerationsPerBatch
大きくなります。 - publisher-republisher マージ エージェントは、世代 101 から 200 を含む世代のバッチを処理します。 このバッチの処理が正常に完了し、それらの世代の関連する変更が再公開にダウンロードされると、publisher-republisher マージ エージェントが中断されます。 中断は、マージ エージェントがジェネレーション 201 から 300 (親アーティクルの変更を含む) を処理する前に発生します。 中断は、ネットワーク接続の損失、クエリ タイムアウトなどが原因である可能性があります。 マージ エージェントは、サーバー側の外部キー制約が NOT FOR REPLICATION としてマークされているため、親行なしで子アーティクル行をコミットできるため、制約のチェックを "中断" できます。
- publisher-republisher マージ エージェントが再び処理を開始する前に、republisher-subscriber マージ エージェントはマージ セッションを開始します。 再公開から変更をダウンロードするプロセスが開始されます。
- republisher-subscriber マージ エージェントがジェネレーション 110 (子アーティクル INSERT) を処理すると、子アーティクルと親アーティクルの間に存在する結合フィルターが評価されます。 親アーティクルの変更はまだ再発行元に届いていないため、マージ エージェントは、これらの子 INSERT が結合フィルターを "修飾" していないと判断します。 マージ エージェントは、第 110 世代を表すMSmerge_genhistory行をダウンロードしますが、その世代の変更はありません。 このマージ エージェントは、セッションを正常に完了します。
- パブリッシャーと再パブリッシュの間のマージ エージェントの後続の実行では、親アーティクル INSERT (世代 201 から 300) を含む世代のバッチが正常に処理され、それらの変更が再パブリッシュリッシャーでコミットされます。
- 最後に、リパブリッシュとサブスクライバー間の後続のマージ エージェント セッションでは、第 250 世代が考慮され、親アーティクル INSERT がサブスクライバーにダウンロードされます。 ただし、サブスクライバーは第 110 世代 (子アーティクルの世代) も認識しているため、マージ エージェントは子アーティクルのパーティションを再評価しません。
これにより、サブスクライバーに正しい親アーティクル行が存在し orphaned
、再パブリッシュ時に子行が存在します。