トランザクション アーティクル - 変更の反映方法の指定
適用対象: SQL Server Azure SQL Managed Instance
トランザクション レプリケーションを使用すると、パブリッシャーからサブスクライバーに変更を反映する方法を指定できます。 パブリッシュされた各テーブルに対して、次の 4 つの方法のいずれかを指定して、各操作 (INSERT、UPDATE、または DELETE) をサブスクライバーに反映できます。
トランザクション レプリケーションのスクリプトを作成し、その後、ストアド プロシージャを呼び出して変更をサブスクライバーに反映するように指定します (既定値)。
INSERT、UPDATE、または DELETE ステートメントを使用して、変更が反映されるように指定します (SQL Server 以外のサブスクライバーの既定値)。
カスタム ストアド プロシージャを使用するように指定します。
この操作がサブスクライバーで実行されないように指定します。 その種類のトランザクションはレプリケートされません。
既定では、トランザクション レプリケーションが、各サブスクライバーにインストールされているストアド プロシージャのセットを使用して、変更をサブスクライバーに伝達します。 パブリッシャーでテーブルに挿入、更新、または削除が発生した場合、各操作はサブスクライバーでのストアド プロシージャへの呼び出しに翻訳されます。 ストアド プロシージャは、テーブル内の列にマップされるパラメーターを受け入れ、それらの列がサブスクライバーで変更されることを許可します。
データの変更をトランザクション アーティクルに反映する方法を設定するには、「 データの変更をトランザクション アーティクルに反映する方法の設定」を参照してください。
既定のストアド プロシージャとカスタム ストアド プロシージャ
各テーブル アーティクルに対して、既定でレプリケーションによって作成されるのは、次の 3 つのプロシージャです。
sp_MSins_< tablename >。挿入処理を行います。
sp_MSupd_< tablename >。更新処理を行います。
sp_MSdel_< tablename >。削除処理を行います。
このプロシージャで使用される <tablename> は、アーティクルがパブリケーションにどのように追加されたか、およびサブスクリプション データベースに所有者が異なる同じ名前のテーブルが含まれているかどうかに応じて異なります。
これらのすべてのプロシージャは、パブリケーションにアーティクルを追加するときに指定したカスタム プロシージャと置き換えることができます。 カスタム プロシージャは、サブスクライバーでの行の更新時にデータを監査テーブルに挿入するなど、アプリケーションにカスタム ロジックが必要な場合に使用されます。 カスタム ストアド プロシージャの指定の詳細については、上記のトピックを参照してください。
既定のレプリケーション プロシージャまたはカスタム プロシージャを指定した場合は、各プロシージャに対する呼び出し構文も指定します (既定のプロシージャを使用する場合は、レプリケーションによって既定値が選択されます)。 呼び出し構文によって、プロシージャに提供されたパラメーターの構造、および各データの変更と共にサブスクライバーに送信される情報の量が決定されます。 詳細については、このトピックの「ストアド プロシージャの呼び出し構文」を参照してください。
カスタム ストアド プロシージャの使用に関する注意点
カスタム ストアド プロシージャを使用する場合は、次の点に注意してください。
ストアド プロシージャ内でロジックをサポートする必要があります。Microsoft はカスタム ロジックをサポートしていません。
レプリケーションによって使用されるトランザクションの競合を防ぐため、カスタム プロシージャでは明示的なトランザクションを使用しないでください。
サブスクライバーにおけるスキーマは、通常、パブリッシャーにおけるスキーマと同一になりますが、列フィルターが使用されている場合は、パブリッシャーのスキーマのサブセットにすることもできます。 ただし、サブスクライバーのスキーマがパブリッシャーのスキーマのサブセットにならないように、データの移動時にスキーマを変換する必要がある場合は、SQL Server 2019 Integration Services (SSIS) を使用することをお勧めします。 詳細については、「 SQL Server Integration Services」を参照してください。
スキーマの変更をパブリッシュされたテーブルに加える場合は、カスタム プロシージャを再生成する必要があります。 詳細については、「カスタム トランザクション プロシージャの再生成によるスキーマ変更の反映」を参照してください。
ディストリビューション エージェントの -SubscriptionStreams パラメーターに対して 1 を超える値を使用した場合は、主キー列に対する更新が成功したことを確認する必要があります。 次に例を示します。
update ... set pk = 2 where pk = 1 -- update 1 update ... set pk = 3 where pk = 2 -- update 2
ディストリビューション エージェントが複数の接続を使用する場合、次の 2 つの更新は、さまざまな接続を経由してレプリケートされる可能性があります。 最初に update 1 が適用される場合は、問題は発生しません。最初に update 2 が適用された場合は、update 1 がまだ発生していないため、"0 行処理されました" というメッセージが返されます。 既定のプロシージャでは、更新による影響を受ける行がない場合にエラーを発生させることによって、このような状況を処理します。
if @@rowcount = 0 if @@microsoftversion>0x07320000 exec sys.sp_MSreplraiserror 20598
エラーの発生によって、ディストリビューション エージェントでは単一の接続による更新の再試行が強制的に行われ、この処理は正常に実行されます。 カスタム ストアド プロシージャには、これと同様のロジックを含める必要があります。
ストアド プロシージャの呼び出し構文
トランザクション レプリケーションで使用されるプロシージャを呼び出すために使用される構文には、5 つのオプションがあります。
CALL 構文。 挿入、更新、および削除に使用できます。 既定では、レプリケーションは挿入と削除に対してこの構文を使用します。
SCALL 構文。 更新のみに使用できます。 既定では、レプリケーションは更新に対してこの構文を使用します。
MCALL 構文。 更新のみに使用できます。
XCALL 構文。 更新と削除に使用できます。
VCALL。 更新可能なサブスクリプションに対して使用されます。 内部のみで使用します。
サブスクライバーに反映されるデータの量は、各方法で異なります。 たとえば、SCALL は、更新によって実際に影響を受ける列だけに対する値の中でデータを渡します。 対照的に、XCALL は、更新によって影響を受けるかどうかに関係なくすべての列、および各列のすべての古いデータ値を必要とします。 多くの場合、SCALL は更新に適していますが、アプリケーションが更新中にすべてのデータ値を必要とする場合は、XCALL を更新に対して使用することもできます。
CALL 構文
INSERT ストアド プロシージャ
INSERT ステートメントを処理するストアド プロシージャには、すべての列に挿入する値が渡されます。
c1, c2, c3,... cn
UPDATE ストアド プロシージャ
UPDATE ステートメントを処理するストアド プロシージャには、アーティクルで定義されているすべての列を更新する値、およびその後に主キー列の元の値が渡されます (どの列が変更されたかは、判別されません)。
c1, c2, c3,... cn, pkc1, pkc2, pkc3,... pkcn
DELETE ストアド プロシージャ
DELETE ステートメントを処理するストアド プロシージャには、主キー列の値が渡されます。
pkc1, pkc2, pkc3,... pkcn
SCALL 構文
UPDATE ストアド プロシージャ
UPDATE ステートメントを処理するストアド プロシージャには、変更された列のみを更新する値、その後に主キー列の元の値、および変更された列を示すビットマスク (binary(n)) パラメーターが渡されます。 次の例では、列 2 (c2) は変更されていません。
c1, , c3,... cn, pkc1, pkc2, pkc3,... pkcn, bitmask
MCALL 構文
UPDATE ストアド プロシージャ
UPDATE ステートメントを処理するストアド プロシージャには、アーティクルで定義されているすべての列を更新する値、その後に主キー列の元の値、および変更された列を示すビットマスク (binary(n)) パラメーターが渡されます。
c1, c2, c3,... cn, pkc1, pkc2, pkc3,... pkcn, bitmask
XCALL 構文
UPDATE ストアド プロシージャ
UPDATE ステートメントを処理するストアド プロシージャには、アーティクルで定義されているすべての列の元の値 (前イメージ) が渡され、その後にアーティクルで定義されているすべての列の更新された値 (後イメージ) が渡されます。
old-c1, old-c2, old-c3,... old-cn, c1, c2, c3,... cn,
DELETE ストアド プロシージャ
DELETE ステートメントを処理するストアド プロシージャには、アーティクルで定義されているすべての列の元の値 (前イメージ) が渡されます。
old-c1, old-c2, old-c3,... old-cn
Note
XCALL は、 text 列および image 列の前イメージ値が NULL であるという前提で使用してください。
例
次のプロシージャは、Adventure Works サンプル データベース内の Vendor Table
に対して作成された既定のプロシージャです。
--INSERT procedure using CALL syntax
create procedure [sp_MSins_PurchasingVendor]
@c1 int,@c2 nvarchar(15),@c3 nvarchar(50),@c4 tinyint,@c5 bit,@c6 bit,@c7 nvarchar(1024),@c8 datetime
as
begin
insert into [Purchasing].[Vendor]([VendorID]
,[AccountNumber]
,[Name]
,[CreditRating]
,[PreferredVendorStatus]
,[ActiveFlag]
,[PurchasingWebServiceURL]
,[ModifiedDate])
values (
@c1
,@c2
,@c3
,@c4
,@c5
,@c6
,@c7
,@c8
)
end
go
--UPDATE procedure using SCALL syntax
create procedure [sp_MSupd_PurchasingVendor]
@c1 int = null,@c2 nvarchar(15) = null,@c3 nvarchar(50) = null,@c4 tinyint = null,@c5 bit = null,@c6 bit = null,@c7 nvarchar(1024) = null,@c8 datetime = null,@pkc1 int
,@bitmap binary(2)
as
begin
update [Purchasing].[Vendor] set
[AccountNumber] = case substring(@bitmap,1,1) & 2 when 2 then @c2 else [AccountNumber] end
,[Name] = case substring(@bitmap,1,1) & 4 when 4 then @c3 else [Name] end
,[CreditRating] = case substring(@bitmap,1,1) & 8 when 8 then @c4 else [CreditRating] end
,[PreferredVendorStatus] = case substring(@bitmap,1,1) & 16 when 16 then @c5 else [PreferredVendorStatus] end
,[ActiveFlag] = case substring(@bitmap,1,1) & 32 when 32 then @c6 else [ActiveFlag] end
,[PurchasingWebServiceURL] = case substring(@bitmap,1,1) & 64 when 64 then @c7 else [PurchasingWebServiceURL] end
,[ModifiedDate] = case substring(@bitmap,1,1) & 128 when 128 then @c8 else [ModifiedDate] end
where [VendorID] = @pkc1
if @@rowcount = 0
if @@microsoftversion>0x07320000
exec sp_MSreplraiserror 20598
end
go
--DELETE procedure using CALL syntax
create procedure [sp_MSdel_PurchasingVendor]
@pkc1 int
as
begin
delete [Purchasing].[Vendor]
where [VendorID] = @pkc1
if @@rowcount = 0
if @@microsoftversion>0x07320000
exec sp_MSreplraiserror 20598
end
go