Transaktionsartiklar – specificera hur förändringar sprids

gäller för:SQL ServerAzure SQL Managed Instance

Med transaktionsreplikering kan du ange hur dataändringar sprids från utgivaren till prenumeranter. För varje publicerad tabell kan du ange ett av fyra sätt som varje åtgärd (INSERT, UPDATE, eller DELETE) ska spridas till prenumeranten:

  • Ange att transaktionsreplikering ska skrivas ut och därefter anropa en lagrad procedur för att sprida ändringar till Prenumeranter (standard).

  • Ange att ändringen ska spridas med hjälp av instruktionen INSERT, UPDATEeller DELETE (standardvärdet för prenumeranter som inte SQL Server).

  • Ange att en anpassad lagrad procedur ska användas.

  • Ange att den här åtgärden inte ska utföras hos någon prenumerant. Transaktioner av den typen replikeras inte.

Som standard sprider transaktionsreplikering ändringar till Prenumeranter via en uppsättning lagrade procedurer som installeras på varje prenumerant. När en infogning, uppdatering eller borttagning sker i en tabell i Publisher översätts åtgärden till ett anrop till en lagrad procedur hos Prenumeranten. Den lagrade proceduren accepterar parametrar som mappar till kolumnerna i tabellen, vilket gör att dessa kolumner kan ändras i Prenumeranten.

Information om hur du anger spridningsmetoden för dataändringar till transaktionsartiklar finns i Ange spridningsmetod för dataändringar till transaktionsartiklar.

Standard- och anpassade lagrade procedurer

Replikering skapar tre standardlagrade procedurer för varje tabellartikel:

  • sp_MSins_<tabellnamn>, som hanterar infogningar.

  • sp_MSupd_<tablename>, som hanterar uppdateringar.

  • sp_MSdel_<tablename>, som hanterar borttagningar.

Tabellnamnet>< som används i proceduren beror på hur du lägger till artikeln i publikationen och om prenumerationsdatabasen innehåller en tabell med samma namn men en annan ägare.

Du kan ersätta någon av dessa procedurer med en anpassad procedur som du specificerar när du lägger till en artikel i en publikation. Använd anpassade procedurer om din applikation kräver anpassad logik, till exempel att infoga data i en revisionstabell när en rad uppdateras hos en prenumerant. För mer information om att specificera anpassade lagrade procedurer, se instruktionsartiklarna i föregående avsnitt.

När du specificerar antingen standardreplikeringsprocedurer eller anpassade procedurer, anger du också anropssyntax för varje procedur. Replikering väljer standardanropssyntax om du använder standardprocedurerna. Anropssyntaxen avgör strukturen för de parametrar som anges i proceduren och hur mycket information som skickas till prenumeranten med varje dataändring. För mer information, se avsnittet "Call Syntax for Stored Procedures" i denna artikel.

Överväganden vid användning av anpassade lagrade procedurer

Tänk på följande när du använder anpassade lagrade procedurer:

  • Du måste stödja logiken i den lagrade proceduren; Microsoft erbjuder inte stöd för anpassad logik.

  • För att undvika konflikter med transaktionerna som används av replikering, använd inte explicita transaktioner i anpassade procedurer.

  • Schemat hos Subscriber är vanligtvis identiskt med schemat hos Publisher, men det kan också vara en delmängd av Publisher-schemat om du använder kolumnfiltrering. Om du behöver transformera schemat när datan flyttas så att schemat hos prenumeranten inte är en delmängd av schemat hos Publisher, använd SQL Server 2019 Integration Services (SSIS). Mer information finns i služba SSIS.

  • Om du gör schemaändringar i en publicerad tabell, generera de anpassade procedurerna igen. Mer information finns i återskapa anpassade transaktionsprocedurer för att återspegla schemaändringar.

  • Om du använder ett värde större än 1 för -SubscriptionStreams-parametern i Distribution Agent, se till att uppdateringar av primärnyckelkolumnerna lyckas. Till exempel:

    update ... set pk = 2 where pk = 1 -- update 1  
    update ... set pk = 3 where pk = 2 -- update 2  
    

    Om Distribution Agent använder mer än en anslutning kan dessa två uppdateringar replikeras över olika anslutningar. Om uppdatering 1 appliceras först är det inga problem. Om uppdatering 2 appliceras först återvänder 0 rows affected den eftersom uppdatering 1 ännu inte har inträffat. Standardprocedurerna hanterar denna situation genom att ange ett fel om inga rader påverkas vid en uppdatering:

    if @@rowcount = 0  
        if @@microsoftversion>0x07320000  
            exec sys.sp_MSreplraiserror 20598  
    

    Att utlösa felet tvingar distributionsagenten att försöka utföra uppdateringarna igen via en enda anslutning, vilket fungerar. Anpassade lagrade procedurer måste innehålla liknande logik.

Anropssyntax för lagrade procedurer

Du kan använda fem olika syntaxalternativ för att anropa de procedurer som transaktionell replikering använder:

  • CALL-syntaxen. Använd denna syntax för insättningar, uppdateringar och borttagningar. Som standard använder replikeringen den här syntaxen för infogningar och borttagningar.

  • SCALL-syntax. Använd denna syntax endast för uppdateringar. Som standard använder replikering den här syntaxen för uppdateringar.

  • MCALL-syntax. Använd denna syntax endast för uppdateringar.

  • XCALL-syntax. Använd denna syntax för uppdateringar och borttagningar.

  • VCALL. Använd denna syntax för uppdaterbara prenumerationer. Endast intern användning.

Varje metod skiljer sig åt i mängden data som skickas till prenumeranten. Till exempel skickar SCALL endast in värden för de kolumner som en uppdatering faktiskt påverkar. XCALL kräver alla kolumner, oavsett om en uppdatering påverkar dem eller inte, samt alla gamla datavärden för varje kolumn. I många fall är SCALL lämpligt för uppdateringar, men om din applikation kräver alla datavärden under en uppdatering stöder XCALL detta behov.

Anropssyntax

INSERT lagrade procedurer
Lagrade procedurer som hanterar INSERT satser får de insatta värdena för alla kolumner:

c1, c2, c3,... cn  

UPDATE lagrade procedurer
Lagrade procedurer som hanterar UPDATE satser får de uppdaterade värdena för alla kolumner som definierats i artikeln, följt av de ursprungliga värdena för primärnyckelkolumnerna. Processen försöker inte avgöra vilka kolumner som ändrats:

c1, c2, c3,... cn, pkc1, pkc2, pkc3,... pkcn  

DELETE lagrade procedurer
Lagrade procedurer som hanterar DELETE satser tar emot värden för primärnyckelkolumnerna:

pkc1, pkc2, pkc3,... pkcn  

SCALL-syntax

UPDATE lagrade procedurer
Lagrade procedurer som hanterar UPDATE satser får de uppdaterade värdena endast för de kolumner som ändrats, följt av de ursprungliga värdena för primärnyckelkolumnerna, och sedan en bitmask (binary(n))-parameter som anger de ändrade kolumnerna. I följande exempel ändrades inte kolumn 2 (c2) längre:

c1, , c3,... cn, pkc1, pkc2, pkc3,... pkcn, bitmask  

MCALL-syntax

UPDATE lagrade procedurer
Lagrade procedurer som hanterar UPDATE satser får de uppdaterade värdena för alla kolumner definierade i artikeln, följt av de ursprungliga värdena för primärnyckelkolumnerna, och sedan en bitmask (binary(n))-parameter som indikerar de ändrade kolumnerna:

c1, c2, c3,... cn, pkc1, pkc2, pkc3,... pkcn, bitmask  

XCALL-syntax

UPDATE lagrade procedurer
Lagrade procedurer som hanterar UPDATE satser får de ursprungliga värdena (förebilden) för alla kolumner definierade i artikeln, följt av de uppdaterade värdena (efterbilden) för alla kolumner definierade i artikeln:

old-c1, old-c2, old-c3,... old-cn, c1, c2, c3,... cn,  

DELETE lagrade procedurer
Lagrade procedurer som hanterar DELETE satser får de ursprungliga värdena (förebilden) för alla kolumner som definieras i artikeln:

old-c1, old-c2, old-c3,... old-cn  

Not

När du använder XCALL ska före-bildvärdena för text och image kolumnerna vara NULL.

Exempel

Följande procedurer är standardprocedurerna som skapats för Vendor Table i Adventure Works-exempeldatabasen.

--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