出版データベースのスキーマ変更を行う

適用対象:SQL ServerAzure SQL Managed Instance

レプリケーションは、パブリッシュされたオブジェクトに対するさまざまなスキーマ変更をサポートしています。 パブリッシュされた適切なオブジェクトに対して、以下に示すスキーマ変更を Microsoft SQL Server パブリッシャーで行った場合、既定ではすべての SQL Server サブスクライバーにその変更が反映されます。

  • ALTER TABLE

  • ALTER TABLE SET LOCK ESCALATIONスキーマ変更レプリケーションが有効で、トポロジーにSQL Server 2005(9.x)またはSQL Server Compact 3.5サブスクライバーが含まれている場合は使用すべきではありません。

  • ALTER VIEW

  • ALTER PROCEDURE

  • ALTER FUNCTION

  • ALTER TRIGGER

    ALTER TRIGGER データ定義言語(DDL)トリガーは複製できないため、データ操作言語(DML)トリガーにのみ使用できます。

重要

テーブルのスキーマ変更は、Transact-SQL またはSQL Server管理オブジェクト(SMO)を使用して行う必要があります。 SQL Server Management Studioでスキーマを変更すると、Management Studioはテーブルをドロップして再作成しようとします。 公開オブジェクトをドロップできないため、スキーマ変更は失敗します。

トランザクション レプリケーションおよびマージ レプリケーションの場合、スキーマ変更はディストリビューション エージェントまたはマージ エージェントが実行されたときに、その増分が反映されます。 スナップショット レプリケーションの場合、スキーマ変更は新しいスナップショットがサブスクライバーで適用されるときに反映されます。 スナップショット レプリケーションでは、同期が行われるたびにスキーマの新しいコピーがサブスクライバーに送信されます。 したがって、以前に挙げたものだけでなく、すべてのスキーマ変更は各同期時に自動的に伝播されます。

パブリケーションでのアーティクルの追加と削除については、「既存のパブリケーションでのアーティクルの追加および削除」を参照してください。

スキーマの変更をレプリケートするには

先に挙げたスキーマの変更はデフォルトで再現されています。 スキーマ変更のレプリケートを無効にする方法については、「 Replicate Schema Changes」を参照してください。

スキーマ変更に関する考慮事項

スキーマ変更をレプリケートする際には、以下の点に注意してください。

一般的な考慮事項

  • スキーマ変更は、Transact-SQL の制限の対象となります。 例えば、 ALTER TABLE は主キーの列を変更することはできません。

  • データ型マッピングは初期スナップショットでのみ行われます。 スキーマの変更は、以前のバージョンのデータ型にマッピングされません。 例えば、SQL Server 2012(11.x)でALTER TABLE ADD datetime2 columnを使うと、2005年(9.x)のサブスクライバー SQL Serverデータ型はnvarcharに変換されません。 場合によっては、スキーマ変更がパブリッシャーでブロックされます。

  • もし出版物をスキーマ変更の伝播を許可するように設定すると、出版物内の関連スキーマオプションの設定に関わらずスキーマ変更が伝播されます。 たとえば、テーブル アーティクルの外部キー制約をレプリケートしないことを選択し、Publisherのテーブルに外部キーを追加するALTER TABLE コマンドを発行すると、外部キーがサブスクライバーのテーブルに追加されます。 この動作を防ぐために、 ALTER TABLE コマンドを発行する前にスキーマ変更の伝播を無効にしてください。

  • スキーマの変更はPublisherでのみ行い、Subscribers(再公開Subscribersを含む)では変更しないでください。 マージ レプリケーションについては、サブスクライバーでスキーマを変更できないようになっています。 トランザクションレプリケーションは変更を防ぐわけではありませんが、変更によってレプリケーションが失敗することがあります。

  • 再パブリッシュ サブスクライバーに反映された変更は、既定でそのサブスクライバーに反映されます。

  • スキーマ変更がPublisherに存在するオブジェクトや制約を参照し、Subscriberには存在しない場合、スキーマ変更はPublisherでは成功しますがSubscriberでは失敗します。

  • 外部キーを追加する際に参照するSubscriber上のすべてのオブジェクトは、Publisher上の対応するオブジェクトと同じ名前と所有者でなければなりません。

  • 明示的なインデックスの追加、削除、変更は再現されません。 各レプリカセットに対して明示的なインデックスを割り当てる変更は個別に実行する必要があります。 制約 (主キー制約など) に対して暗黙的に作成されたインデックスはサポートされます。

  • レプリケーションが管理するアイデンティティカラムを変更または削除することはサポートされていません。 ID 列の自動管理の詳細については、「ID 列のレプリケート」を参照してください。

  • 非決定性関数を含むスキーマ変更はサポートされません。なぜなら、PublisherとSubscriberのデータが異なる(非収束と呼ばれます)になる可能性があるからです。 たとえば、 ALTER TABLE SalesOrderDetail ADD OrderDate DATETIME DEFAULT GETDATE()というコマンドをパブリッシャーで実行した場合、このコマンドがサブスクライバーにレプリケートされて実行されると異なる値になります。 非決定的関数の詳細については、「 Deterministic and Nondeterministic Functions」を参照してください。

  • 名前の制約を明示的に設定しましょう。 制約に明示的に名前を付けない場合、SQL Serverが制約名を生成し、その名前はPublisherとSubscriberごとに異なります。 この違いは、スキーマ変更のレプリケーション時に問題を引き起こすことがあります。 例えば、Publisherでカラムをドロップし、依存制約が削除された場合、レプリケーションはSubscriberでその制約をドロップしようとします。 サブスクライバーでのドロップは、制約名が異なるため失敗します。 制約の名前付けの問題によって同期に失敗する場合、サブスクライバー側で制約を手動で削除して、マージ エージェントを再実行してください。

  • レプリケーション用にテーブルを公開した場合、すでに公開スナップショットを生成している場合、そのテーブルの列をXMLのデータ型に変更することはできません。 列を変更するには、まず複製を除去する必要があります。

  • 公開されたテーブルでDDLを実行する際、未コミットのリードはサポートされる分離レベルではありません。

  • スキーマ変更が公開されたオブジェクトに対して行われるトランザクションのコンテキストを変更するために SET CONTEXT_INFO を使わないでください。

列を追加する

  • 新しい列をテーブルに追加し、その列を既存の出版物に含めるには、 ALTER TABLE <Table> ADD <Column>を実行します。 この列は、既定ですべてのサブスクライバーにレプリケートされます。 列は NULL 値を許可するか、デフォルトの制約を含める必要があります。 列の追加に関する詳細は、本記事の「マージレプリケーション」セクションをご覧ください。

  • 新しい列をテーブルに追加し、その列を既存の公開に含めない場合は、スキーマ変更のレプリケーションを無効にし、その後 ALTER TABLE <Table> ADD <Column>を実行します。

  • 既存のパブリケーションに既存の列を含めるには、sp_articlecolumn (Transact-SQL)、sp_mergearticlecolumn (Transact-SQL)、または [パブリケーションのプロパティ - <パブリケーション]> ダイアログ ドロップダウン リストを使用します。

    詳しくは、「 Define and Modify a Column Filter」をご覧ください。 この操作ではサブスクリプションの初期化が必要です。

  • 公開されたテーブルにアイデンティティカラムを追加することはサポートされていません。なぜなら、カラムがサブスクライバーに複製された際に収束がなくなる可能性があるからです。 パブリッシャーの ID 列の値は、影響を受けるテーブルの行が物理的に格納されている順序に依存します。 サブスクライバーで行が同じように格納されているとは限らないため、同じ行で ID 列の値が異なる可能性があります。

列の削除

  • 既存の出版物から列を落とし、Publisherのテーブルから列を落とすには、ALTER TABLE <Table> DROP <Column>を実行します。 この列は、既定ですべてのサブスクライバーのテーブルから削除されます。

  • 既存の出版物から列を削除し、その列をパブリッシャーのテーブルからは削除しない場合は、sp_articlecolumn (Transact-SQL)、sp_mergearticlecolumn (Transact-SQL)、または [パブリケーションのプロパティ - <パブリケーション]> ダイアログ ドロップダウン リストを使用します。

    詳しくは、「 Define and Modify a Column Filter」をご覧ください。 この操作には新しいスナップショットを生成する必要があります。

  • データベース内のどの出版物の記事のフィルター条項をこの列に付けることはできません。

  • 公開記事からカラムを削除する際は、データベースに影響を与える可能性のある制約、インデックス、または属性を考慮してください。 次に例を示します。

    • トランザクション出版物の記事から主キーに使われる列を削除することはできません。なぜならレプリケーションがそれらを使うからです。

    • マージ出版物の記事から rowguid 列を削除したり、サブスクリプションの更新をサポートするトランザクション出版物の記事から mstran_repl_version 列を削除することはできません。なぜならレプリケーションはそれらを使うからです。

    • インデックスの変更は購読者に伝播されません。 Publisherでカラムをドロップして依存インデックスがドロップした場合、そのインデックスドロップは再現されません。 パブリッシャー側で列を削除する前に、サブスクライバー側でインデックスを削除する必要があります。この操作を行っておくと、列をパブリッシャーからサブスクライバーにレプリケートするときに列の削除に成功します。 サブスクライバー側のインデックスが原因で同期に失敗する場合、手動でインデックスを削除して、マージ エージェントを再実行してください。

    • 制約には明示的に名前を付けて、外せるようにしましょう。 詳細については、この記事の冒頭にある「一般的な考慮事項」セクションをご覧ください。

トランザクションレプリケーション

  • スキーマ変更は、以前のバージョンの SQL Server を実行しているサブスクライバーにも反映されますが、DDL ステートメントに含まれているすべての構文が、サブスクライバーで実行されているバージョンでサポートされている必要があります。

    サブスクライバーがデータを再パブリッシュする場合にサポートされるスキーマ変更は、列の追加と削除のみです。 これらの変更は、ALTER TABLE DDL 構文ではなく、Publisher で sp_repladdcolumn (Transact-SQL) と sp_repldropcolumn (Transact-SQL) を使用して行ってください。

  • スキーマの変更は非SQL Serverのサブスクライバーには複製されません。

  • スキーマの変更はSQL Server以外のパブリッシャーから伝播されることはありません。

  • テーブルとして複製されたインデックスビューは変更できません。 インデックスビューとして複製されたインデックスビューを変更することはできますが、変更するとインデックスビューではなく通常のビューになります。

  • パブリケーションが即時更新サブスクリプションまたはキュー更新サブスクリプションをサポートしている場合は、スキーマ変更を行う前にシステムを静止状態にしてください。つまり、パブリッシャーおよびサブスクライバーでパブリッシュされたテーブルに対するすべてのアクティビティを停止し、保留中のデータ変更をすべてのノードに反映させてください。 スキーマの変更がすべてのノードに伝播した後、公開されたテーブルでの活動が再開されます。

  • パブリケーションがピアツーピア トポロジにある場合は、スキーマを変更する前にシステムを停止状態にしてください。 詳細については、「レプリケーション トポロジの停止 (レプリケーション Transact-SQL プログラミング)」を参照してください。

  • テーブルにタイムスタンプの列を追加し、そのタイムスタンプを binary(8) にマッピングすると、すべてのアクティブな購読者に対して記事が再初期化されます。

マージ レプリケーション

  • マージレプリケーションがスキーマ変更をどのように処理するかは、公開互換性レベルや、スナップショットがネイティブモード(デフォルト)またはキャラクターモードに設定されているかによって異なります。

    • スキーマの変更を再現するには、公開互換性レベルを少なくとも90RTMに設定してください。 加入者が以前のSQL Serverを使用している場合や互換性レベルが90RTM未満の場合は、sp_repladdcolumn(Transact-SQL)とsp_repldropcolumn(Transact-SQL)を使ってカラムの追加・削除を行います。 ただし、これらのプロシージャは非推奨です。

    • SQL Server 2008 (10.0.x) で導入されたデータ型の列を既存のアーティクルに追加すると、 SQL Server は次のように動作します。

      100RTM、ネイティブ モードのスナップショット 100RTM、キャラクター モードのスナップショット その他すべての互換性レベル
      hierarchyid 変更を許可する 変更をブロックする 変更をブロックする
      geography および geometry 変更を許可する 変更を許可する* 変更をブロックする
      ファイル ストリーム (filestream) 変更を許可する 変更をブロックする 変更をブロックする
      date、 time、 datetime2、および datetimeoffset 変更を許可する 変更を許可する* 変更をブロックする

      *SQL Server Compact サブスクライバーは、これらのデータ型をサブスクライバー側で変換します。

  • スキーマ変更の適用時にエラー (サブスクライバーで利用できないテーブルを参照する外部キーを追加した結果のエラーなど) が発生すると、同期が失敗し、サブスクリプションを再初期化しなければならなくなります。

  • 結合フィルターやパラメーター化されたフィルターに含まれている列に対してスキーマ変更を行う場合は、すべてのサブスクリプションを再初期化し、スナップショットを再生成する必要があります。

  • マージ レプリケーションには、トラブルシューティングの際にスキーマ変更をスキップするストアド プロシージャが用意されています。 詳細については、「 sp_markpendingschemachange (Transact-SQL) 」および「sp_enumeratependingschemachanges (Transact-SQL)」を参照してください。