パブリッシャとサブスクライバのデータが一致しない

パブリッシャとサブスクライバのデータは、次の場合に未集約 (データが一致しない状態) と見なされます。

  • サブスクライバとパブリッシャにある行数が異なり、パブリケーションがフィルタ選択されていない場合。パブリケーションがフィルタ選択されている場合は、行数が異なることが予想されます。

  • 1 つ以上の行内のデータが、パブリッシャとサブスクライバで内容が異なる場合。

説明

パブリッシャとサブスクライバのデータは、さまざまな理由で未集約になる可能性があります。

  • サブスクライバで読み取り専用であるべきデータが更新された場合。サブスクリプション データベースは、マージ レプリケーション、更新可能なサブスクリプションを使用したトランザクション レプリケーション、またはピア ツー ピア トランザクション レプリケーションを使用する場合を除き、読み取り専用として扱う必要があります。

  • サブスクライバで、トリガが使用された場合。トリガによって、サブスクライバにあるデータが変更されたり、ROLLBACK を発行した場合にそのデータが更新されない場合があります。

  • スクリプトが、サブスクライバではレプリケーションによって実行され、パブリッシャでは実行されない場合。

  • トランザクション パブリケーションに対するストアド プロシージャ実行のレプリケーションを行うと、サブスクライバでは結果が異なる場合。

  • 制約の違反またはその他の問題点によって、サブスクライバで行を挿入、更新、または削除できない場合。

ユーザーの操作

次の操作は、データが未集約かどうかを判別する方法、およびデータを集約する方法について説明しています。

  1. 検証を行うか、tablediff ユーティリティを使用して、データが未集約であるかどうかを判別します。

    • ディストリビューション エージェントまたはマージ エージェントを実行できる場合は、バイナリ チェックサム検証を実行して、データが不足しているかどうかを判別します。行数検証も使用できますが、この方法では、データの内容の違いは示されません。詳細については、「レプリケートされたデータの検証」を参照してください。

    • ディストリビューション エージェントまたはマージ エージェントを実行できない場合は、tablediff ユーティリティを実行して、データが未集約であるかどうかを判別します。レプリケートされたテーブルでこのユーティリティを使用する方法の詳細については、「レプリケートされたテーブルを比較して相違があるかどうかを確認する方法 (レプリケーション プログラミング)」を参照してください。

  2. データが未集約である場合、tablediff ユーティリティを使用して Transact-SQL スクリプトを生成し、データを集約させます。詳細については、「tablediff ユーティリティ」を参照してください。

データが未集約になる原因への対処

次の操作は、「説明」で示した原因への対処方法です。

  • サブスクライバで、レプリケーション以外でデータが更新された場合。

    • ユーザーがサブスクライバでデータを挿入、更新、および削除できるようにする場合は、マージ レプリケーション、更新可能なサブスクリプションを使用したトランザクション レプリケーション、またはピア ツー ピア トランザクション レプリケーションを使用します。詳細については、「マージ レプリケーションの概要」および「トランザクション レプリケーションで使用するパブリケーションの種類」を参照してください。

    • ユーザーがサブスクライバでデータの挿入、更新、および削除を行えないようにする場合は、ROLLBACK という語を含み、NOT FOR REPLICATION オプション (レプリケーション エージェントが操作を実行するときにトリガが起動されないようにするオプション) を使用する各テーブルに対して、トリガを作成します。次に例を示します。

      USE AdventureWorks
      GO
      CREATE TRIGGER prevent_user_dml
      ON Person.Address
      FOR INSERT, UPDATE, DELETE
      NOT FOR REPLICATION
      AS
      ROLLBACK
      

      詳細については、「CREATE TRIGGER (Transact-SQL)」および「NOT FOR REPLICATION を使用した制約、ID、およびトリガの制御」を参照してください。

  • サブスクライバで、トリガが使用された場合。サブスクライバでのトリガは、未集約やその他の問題点の原因とならないように適切に管理する必要があります。

    • トリガは、マージ レプリケーション、更新可能なサブスクリプションを使用したトランザクション レプリケーション、またはピア ツー ピア トランザクション レプリケーションを使用した場合にのみ、サブスクライバでデータが変更されるようにする必要があります。詳細については、「マージ レプリケーションの概要」および「トランザクション レプリケーションで使用するパブリケーションの種類」を参照してください。

    • 多くの場合、トリガは NOT FOR REPLICATION オプションを使用する必要があります。データを追跡テーブルに挿入するトリガについて考えてみましょう。ユーザーが最初に行を挿入した場合、トリガが起動され追跡テーブルに行が入力されるのは、適切な動作です。ただし、データがサブスクライバにレプリケートされた場合は、不要な行が追跡テーブルに挿入されるのを防ぐために、トリガが起動されないようにする必要があります。

      トリガに ROLLBACK ステートメントが含まれており、そのトリガが NOT FOR REPLICATION オプションを使用しない場合、サブスクライバにレプリケートされた行は適用されない可能性があります。

    • トランザクション レプリケーションの場合、XACT_ABORT の設定、およびトリガ内での COMMIT および ROLLBACK ステートメントの使用に関する注意事項がさらにあります。詳細については、「トランザクション レプリケーションに関する注意点」の「トリガ」を参照してください。

  • スクリプトが、サブスクライバではレプリケーションによって実行され、パブリッシャでは実行されない場合。

    sp_addpublicationsp_addmergepublication@pre_snapshot_script パラメータと @post_snapshot_script パラメータを使用すると、スナップショットの適用前と適用後にスクリプトが実行されるように指定できます。詳細については、「スナップショット適用前および適用後のスクリプトの実行」を参照してください。ストアド プロシージャ sp_addscriptexec を使用すると、同期処理中にスクリプトを実行できます。詳細については、「同期中にスクリプトを実行する方法 (レプリケーション Transact-SQL プログラミング)」を参照してください。

    これらのスクリプトは、通常、サブスクライバでのログインの追加など、管理タスクに使用されます。スクリプトがサブスクライバで読み取り専用として扱われるデータの更新に使用される場合、管理者は結果が未集約にならないことを確認する必要があります。

  • トランザクション パブリケーションに対するストアド プロシージャ実行のレプリケーションを行うと、サブスクライバでは結果が異なる場合。

    ストアド プロシージャの実行をレプリケートする場合は、サブスクリプションを初期化したときにプロシージャの定義がサブスクライバにレプリケートされます。プロシージャがパブリッシャで実行されると、レプリケーションは対応するプロシージャをサブスクライバで実行します。詳細については、「トランザクション レプリケーションにおけるパブリッシング ストアド プロシージャの実行」を参照してください。

    ストアド プロシージャによって、サブスクライバで異なる操作が実行された場合、またはパブリッシャとは異なるデータが処理された場合、データの未集約が発生する可能性があります。計算を実行してから、この計算に基づいたデータを挿入するプロシージャの場合について考えます。サブスクライバがフィルタ選択され、サブスクライバでの計算が別のデータに基づいている場合は、サブスクライバに挿入される結果が異なったり、挿入が発生しない可能性があります。

  • 制約の違反、またはその他の問題点によって、サブスクライバで行を挿入、更新、または削除できない場合。

    トランザクション レプリケーションの場合、制約違反はエラーとして扱われます。既定では、エラーが発生するとディストリビューション エージェントでの同期が停止されます (これらのエラーをスキップする方法については、「トランザクション レプリケーションでのエラーのスキップ」を参照してください)。マージ レプリケーションの場合、制約違反は競合として扱われます。競合はログに記録されますが、競合によってマージ エージェントでの同期が停止することはありません。どちらの種類のレプリケーションでも、あるノードで成功した挿入、更新、または削除が別のノードでは成功しない場合に、制約違反によってデータの未集約が発生する可能性があります。

    テーブルがパブリッシュされると、NOT FOR REPLICATION オプション セットを使用してサブスクリプション データベース内に外部キー制約と CHECK 制約を作成するように、既定のスキーマ オプションによって指定されます。制約に対して異なる設定がアプリケーションに必要な場合は、スキーマ オプションを変更します。詳細については、「スキーマ オプションを指定する方法 (SQL Server Management Studio)」および「スキーマ オプションを指定する方法 (レプリケーション Transact-SQL プログラミング)」を参照してください。