サブスクライバーにデータが配信されない
データがサブスクライバーに配信されない場合、大きく分けて以下の 2 つの理由が考えられます。
フィルター選択、エージェントの問題、またはその他のレプリケーション エラーのため、データが適用されていない。
データが適用された後、サブスクライバーで削除されている。
説明
データがサブスクライバーに配信されない場合には、以下のようなさまざまな原因が考えられます。
テーブルがフィルター選択されており、指定のサブスクライバーに配信される変更が存在しない。
1 つ以上のエージェントが実行されていない、またはエラーによる障害が発生している。
トランザクション サブスクリプションがスナップショットなしで初期化されており、パブリケーションの作成以降にパブリッシャーでデータが変更されている。
トランザクション パブリケーションに対するストアド プロシージャ実行のレプリケーションを行うと、サブスクライバーでは結果が異なる。
トランザクション アーティクルが使用する INSERT ストアド プロシージャの条件が満たされていない。
ユーザー、レプリケーション スクリプト、またはその他のアプリケーションによってデータが削除されている。
トリガーによってデータが削除されている、またはトリガーに ROLLBACK ステートメントが含まれている。
ユーザーの操作
サブスクライバーにデータが配信されない原因について診断を行う前に、検証または tablediff ユーティリティを使用して、行が存在していないかどうかを確認することをお勧めします。
ディストリビューション エージェントまたはマージ エージェントを実行できる場合は、バイナリ チェックサム検証を実行して、データが不足しているかどうかを判別します。行数検証も使用できますが、この方法では、データの内容の違いは示されません。詳細については、「レプリケートされたデータの検証」を参照してください。
ディストリビューション エージェントまたはマージ エージェントを実行できない場合は、tablediff ユーティリティを実行して、データが存在しないかどうかを判別します。レプリケートされたテーブルでこのユーティリティを使用する方法の詳細については、「レプリケートされたテーブルを比較して相違があるかどうかを確認する方法 (レプリケーション プログラミング)」を参照してください。
データが存在しない原因への対処
次の操作は、「説明」で示した原因への対処方法です。
テーブルがフィルター選択されており、指定のサブスクライバーに配信される変更が存在しない。
サブスクライバーに行が存在しないのは、その行がパブリケーションのフィルターの条件を満たしていないためにレプリケートされなかったことが原因と考えられます。すべての種類のレプリケーションで静的フィルターがサポートされており、またマージ レプリケーションではパラメーター化されたフィルターと結合フィルターもサポートされています。詳細については、「パブリッシュされたデータのフィルター選択」を参照してください。パブリケーションで 1 つ以上のアーティクルがフィルター選択されている場合、以下のプロシージャを実行してフィルター句の値を確認します。
スナップショット パブリケーションおよびトランザクション パブリケーションの静的フィルターでは、sp_helparticle (Transact-SQL) によって filter_clause 列が返されます。
マージ パブリケーションの静的フィルターまたはパラメーター化されたフィルターでは、sp_helpmergearticle (Transact-SQL) によって subset_filterclause 列が返されます。
マージ パブリケーションの結合フィルターでは、sp_helpmergefilter (Transact-SQL) によって join_filterclause 列が返されます。
このフィルター句を使用して、存在しない行がフィルターの条件を満たすかどうかを確認します。たとえば、パブリッシャーのテーブルに対してフィルター句を実行することで、返されたデータがサブスクライバーのデータに一致するかどうかを判別できます。
1 つ以上のエージェントが実行されていない、またはエラーによる障害が発生している。
サブスクリプションを初期化する場合には、パブリケーションのスナップショット エージェントが完了してから、ディストリビューション エージェントまたはマージ エージェントにスナップショットを適用するようにします。エージェントの完了前にスナップショットを適用しようとすると、"パブリケーション '%1!s!' の初期スナップショットはまだ使用できません。" というエラーが発生します。
トランザクション レプリケーションの場合は、ディストリビューション エージェントとログ リーダー エージェントが、マージ レプリケーションの場合はマージ エージェントがそれぞれ実行中であることを確認します。これらのエージェントの開始の詳細については、「レプリケーション エージェントの起動および停止方法 (SQL Server Management Studio)」および「レプリケーション エージェント実行可能ファイルの概念」を参照してください。
エラーが原因でエージェントが停止した場合は、エージェントのエラーの詳細を表示して根本的な原因を確認します。スナップショット エージェントおよびログ リーダー エージェントのエラーの詳細を表示する方法の詳細については、「パブリケーションに関連付けられているエージェントの情報を表示したりタスクを実行する方法 (レプリケーション モニタ)」を参照してください。ディストリビューション エージェントおよびマージ エージェントの詳細については、「サブスクリプションに関連付けられているエージェントの情報を表示し、タスクを実行する方法 (レプリケーション モニタ)」を参照してください。エラーの発生が継続する場合は、エージェントのログ記録を増やし、ログの出力ファイルを指定します。エラーのコンテキストによっては、エラーや他のエラー メッセージにつながる手順が示される可能性もあります。詳細については、「レプリケーション エージェント (トラブルシューティング)」を参照してください。
データが配信されない原因となる一般的なエラーには、権限の問題と制約違反があります。権限の問題の詳細については、「データのレプリケートを妨げるセキュリティの問題」を参照してください。制約違反が発生すると、サブスクライバーに行を挿入できなくなります。
トランザクション レプリケーションの場合、制約違反はエラーとして扱われます。既定では、エラーが発生すると、ディストリビューション エージェントでの同期が停止されます (これらのエラーをスキップする方法については、「トランザクション レプリケーションでのエラーのスキップ」を参照してください)。マージ レプリケーションの場合、制約違反は競合として扱われます。競合はログに記録されますが、競合によってマージ エージェントでの同期が停止することはありません。どちらの種類のレプリケーションでも、あるノードで成功した挿入、更新、または削除が別のノードでは成功しない場合に、制約違反によってデータの未集約が発生する可能性があります。
テーブルがパブリッシュされると、NOT FOR REPLICATION オプション セットを使用してサブスクリプション データベース内に外部キー制約と CHECK 制約を作成するように、既定のスキーマ オプションによって指定されます。制約に対して異なる設定がアプリケーションに必要な場合は、スキーマ オプションを変更します。詳細については、「スキーマ オプションを指定する方法 (SQL Server Management Studio)」および「スキーマ オプションを指定する方法 (レプリケーション Transact-SQL プログラミング)」を参照してください。
トランザクション サブスクリプションがスナップショットなしで初期化されており、パブリケーションの作成後パブリッシャーでデータが変更されている。
バックアップからのパブリケーションの初期化が有効になっている場合、パブリケーションが作成されるとすぐに、パブリッシュされたテーブルに対する変更が追跡され、パブリケーション データベースのログに記録されるようになります。サブスクリプションが初期化されると、ディストリビューション データベースで使用可能な場合に限り、保留中の変更がサブスクライバーに配信されます。
[レプリケーションのサポートのみ] オプションを使用してサブスクリプションを初期化する場合、バックアップを使用して初期化する場合と異なり、サブスクリプションを追加した時点でデータとスキーマが正しく同期されていることを手動またはアプリケーションで確認する必要があります。たとえば、データとスキーマをサブスクライバーにコピーしてからサブスクリプションを追加するまでの間にパブリッシャー上で処理が実行されると、この処理による変更がサブスクライバーにレプリケートされない場合があります。
詳細については、「スナップショットを使用しないトランザクション サブスクリプションの初期化」を参照してください。
トランザクション パブリケーションに対するストアド プロシージャ実行のレプリケーションを行うと、サブスクライバーでは結果が異なる。
ストアド プロシージャの実行をレプリケートする場合は、サブスクリプションを初期化したときに、プロシージャの定義がサブスクライバーにレプリケートされます。プロシージャがパブリッシャーで実行されると、レプリケーションは対応するプロシージャをサブスクライバーで実行します。詳細については、「トランザクション レプリケーションにおけるパブリッシング ストアド プロシージャの実行」を参照してください。
ストアド プロシージャによって、サブスクライバーで異なる操作が実行された場合、またはパブリッシャーとは異なるデータが処理された場合、データの未集約が発生する可能性があります。計算を実行してから、この計算に基づいたデータを挿入するプロシージャの場合について考えます。サブスクライバーがフィルター選択され、サブスクライバーでの計算が別のデータに基づいている場合は、サブスクライバーに挿入される結果が異なる可能性、または挿入が発生しない可能性があります。
トランザクション アーティクルが使用する INSERT ストアド プロシージャの条件が満たされていない。
既定では、トランザクション レプリケーションは、一連のストアド プロシージャを使用して変更をサブスクライバーに反映します。これらのプロシージャをカスタマイズして、アプリケーションで必要となるビジネス ロジックを含めることもできます。詳細については、「トランザクション アーティクルに変更を反映する方法の指定」を参照してください。INSERT ストアド プロシージャのロジックで条件が満たされない場合、挿入処理は実行されません。あるテーブル (テーブル A) の特定の値を別のテーブル (テーブル B) に挿入する前に確認するようにカスタマイズされたプロシージャについて考えてみます。エラーまたはデータのレプリケートが完了していないためにテーブル A の値が利用できない場合、テーブル B に挿入されるはずの行が存在しなくなります。
ユーザー、レプリケーション スクリプト、またはその他のアプリケーションによってデータが削除されている。
ユーザーがサブスクライバーでデータを削除できるようにする場合は、マージ レプリケーション、更新可能なサブスクリプションを使用したトランザクション レプリケーション、またはピア ツー ピア トランザクション レプリケーションを使用します。データの削除はパブリッシャーに反映されます。その結果、パブリッシャーとサブスクライバーのデータは最終的に集約されます。詳細については、「マージ レプリケーションの概要」および「トランザクション レプリケーションで使用するパブリケーションの種類」を参照してください。
ユーザーがサブスクライバーでデータ削除を行えないようにする場合は、ROLLBACK という語を含み、NOT FOR REPLICATION オプション (レプリケーション エージェントが操作を実行するときにトリガーが起動されないようにする) を使用する各テーブルに対して、トリガーを作成します。以下に例を示します。
USE AdventureWorks2008R2; 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、およびトリガの制御」を参照してください。
レプリケーションでは、スナップショット適用前、適用後および同期中にスクリプトを実行できます。sp_addpublication と sp_addmergepublication の @pre_snapshot_script パラメーターと @post_snapshot_script パラメーターを使用すると、スナップショットの適用前と適用後にスクリプトが実行されるように指定できます。詳細については、「スナップショット適用前および適用後のスクリプトの実行」を参照してください。ストアド プロシージャ sp_addscriptexec を使用すると、同期処理中に、スクリプトを実行できます。詳細については、「同期中にスクリプトを実行する方法 (レプリケーション Transact-SQL プログラミング)」を参照してください。
これらのスクリプトは、通常、サブスクライバーでのログインの追加など、管理タスクに使用されます。スクリプトがサブスクライバーで読み取り専用として扱われるデータの削除に使用される場合、管理者は、結果が未集約にならないことを確認する必要があります。
トリガーによってデータが削除されている、またはトリガーに ROLLBACK ステートメントが含まれている。
サブスクライバーでのトリガーは、未集約やその他の問題点の原因とならないように適切に管理する必要があります。
トリガーは、マージ レプリケーション、更新可能なサブスクリプションを使用したトランザクション レプリケーション、またはピア ツー ピア トランザクション レプリケーションを使用した場合にのみ、サブスクライバーでデータが変更されるようにする必要があります。詳細については、「マージ レプリケーションの概要」および「トランザクション レプリケーションで使用するパブリケーションの種類」を参照してください。
多くの場合、トリガーは NOT FOR REPLICATION オプションを使用する必要があります。トリガーに ROLLBACK ステートメントが含まれており、そのトリガーが NOT FOR REPLICATION オプションを使用しない場合、サブスクライバーにレプリケートされた行は、適用されない可能性があります。
トランザクション レプリケーションの場合、XACT_ABORT の設定、およびトリガー内での COMMIT および ROLLBACK ステートメントの使用に関するその他の注意事項があります。詳細については、「トランザクション レプリケーションに関する注意点」の「トリガー」を参照してください。