Transaktionale Artikel – spezifizieren, wie Änderungen weitergegeben werden

Gilt für:SQL ServerAzure SQL Managed Instance

Bei der Transaktionsreplikation können Sie angeben, wie Datenänderungen vom Verleger an den Abonnenten weitergegeben werden. Für jede veröffentlichte Tabelle können Sie eine von vier Möglichkeiten angeben, wie jeder Vorgang (INSERT, UPDATEoder DELETE) an den Abonnenten weitergegeben werden soll:

  • Geben Sie an, dass die Transaktionsreplikation eine gespeicherte Prozedur als Skript erstellen und anschließend aufrufen soll, um Änderungen an die Abonnenten weiterzugeben (Standardeinstellung).

  • Geben Sie an, dass die Änderung mithilfe einer INSERT-, UPDATE- oder DELETE-Anweisung weitergegeben werden soll (Standard für Nicht-SQL-Server-Abonnenten).

  • Angeben, dass eine benutzerdefinierte gespeicherte Prozedur verwendet wird.

  • Angeben, dass diese Aktion auf keinem Abonnenten ausgeführt wird. Transaktionen dieses Typs werden nicht repliziert.

Standardmäßig gibt die Transaktionsreplikation Änderungen an Abonnenten mithilfe einer Reihe gespeicherter Prozeduren weiter, die auf jedem Abonnenten gespeichert sind. Wenn beim Publisher ein Einfüge-, Aktualisierungs- oder Löschvorgang in einer Tabelle erfolgt, wird der Vorgang in einen Aufruf einer gespeicherten Prozedur beim Subscriber umgesetzt. Die gespeicherte Prozedur nimmt Parameter an, die den Spalten der Tabelle entsprechen, sodass diese Spalten beim Subscriber geändert werden können.

Informationen zum Festlegen der Propagierungsmethode für Datenänderungen an Transaktionsartikeln finden Sie unter Festlegen der Propagierungsmethode für Datenänderungen an Transaktionsartikeln.

Standardmäßige und benutzerdefinierte gespeicherte Prozeduren

Replikation erstellt für jeden Tabellenartikel drei standardmäßig gespeicherte Prozeduren:

  • sp_MSins_<Tabellenname>, das INSERT-Vorgänge verarbeitet.

  • sp_MSupd_<Tabellenname>, die für Updates zuständig ist.

  • sp_MSdel_<Tabellenname>, das Löschvorgänge behandelt.

Der < im Verfahren verwendete Tabellenname> hängt davon ab, wie Sie den Artikel zur Publikation hinzufügen und ob die Abonnementdatenbank eine Tabelle mit demselben Namen, aber einem anderen Besitzer enthält.

Sie können jede dieser Verfahren durch ein individuelles Verfahren ersetzen, das Sie beim Hinzufügen eines Artikels zu einer Publikation festlegen. Verwenden Sie benutzerdefinierte Prozeduren, wenn Ihre Anwendung benutzerdefinierte Logik benötigt, zum Beispiel das Einfügen von Daten in eine Audit-Tabelle, wenn eine Zeile bei einem Abonnenten aktualisiert wird. Weitere Informationen zur Spezifizierung benutzerdefinierter gespeicherter Verfahren finden Sie in den im vorherigen Abschnitt aufgeführten Anleitungsartikeln.

Wenn Sie entweder die Standard-Replikationsprozeduren oder benutzerdefinierte Prozeduren angeben, geben Sie auch für jede Prozedur die Aufrufsyntax an. Replikation wählt die Standard-Aufrufsyntax aus, wenn du die Standardprozeduren verwendest. Die Aufrufsyntax legt die Struktur der für die Prozedur bereitgestellten Parameter fest und welche Informationen bei jeder Datenänderung an den Abonnenten gesendet werden. Weitere Informationen finden Sie im Abschnitt „Aufrufsyntax für gespeicherte Prozeduren“ in diesem Artikel.

Überlegungen zur Verwendung benutzerdefinierter gespeicherter Verfahren

Berücksichtigen Sie bei der Verwendung benutzerdefinierter gespeicherter Prozeduren die folgenden Überlegungen:

  • Du musst die Logik im gespeicherten Verfahren unterstützen; Microsoft bietet keine Unterstützung für benutzerdefinierte Logik an.

  • Um Konflikte mit den von der Replikation verwendeten Transaktionen zu vermeiden, verwenden Sie keine expliziten Transaktionen in benutzerdefinierten Verfahren.

  • Das Schema beim Subscriber ist typischerweise identisch mit dem beim Publisher, kann aber auch eine Teilmenge des Publisher-Schemas sein, wenn man Spaltenfilterung verwendet. Wenn du das Schema während der Datenbewegung transformieren musst, sodass das Schema beim Subscriber kein Teilmenge des Schemas im Publisher ist, nutze SQL Server 2019 Integration Services (SSIS). Weitere Informationen finden Sie unter SQL Server Integration Services.

  • Wenn du Schemaänderungen an einer veröffentlichten Tabelle vornimmst, generiere die benutzerdefinierten Prozeduren neu. Weitere Informationen finden Sie unter Erneutes Generieren von Transaktionsprozeduren zur Erfassung von Schemaänderungen.

  • Wenn Sie einen Wert größer als 1 für den -SubscriptionStreams-Parameter des Verteilungs-Agent verwenden, stellen Sie sicher, dass Aktualisierungen der Primärschlüsselspalten erfolgreich sind. Zum Beispiel:

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

    Wenn der Verteilungs-Agent mehr als eine Verbindung verwendet, können sich diese beiden Updates über verschiedene Verbindungen replizieren. Wenn Update 1 zuerst angewendet wird, gibt es kein Problem. Wenn Update 2 zuerst angewendet wird, kehrt es zurück, 0 rows affected weil Update 1 noch nicht stattgefunden hat. Die Standardverfahren lösen diese Situation, indem sie einen Fehler auslösen, wenn bei einer Aktualisierung keine Zeilen betroffen sind:

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

    Das Auslösen des Fehlers zwingt den Verteilungs-Agent dazu, die Updates über eine einzelne Verbindung erneut auszuführen, was erfolgreich ist. Benutzerdefinierte gespeicherte Prozeduren müssen eine ähnliche Logik einschließen.

Aufrufsyntax für gespeicherte Prozeduren

Sie können fünf verschiedene Syntaxoptionen verwenden, um die Verfahren aufzurufen, die transaktionale Replikation verwendet:

  • CALL-Syntax. Verwenden Sie diese Syntax für Einfügungen, Aktualisierungen und Löschungen. Die Replikation verwendet diese Syntax standardmäßig für Einfügungen und Löschungen.

  • SCALL-Syntax. Verwenden Sie diese Syntax nur für Updates. Die Replikation verwendet diese Syntax standardmäßig für Updates.

  • MCALL-Syntax. Verwenden Sie diese Syntax nur für Updates.

  • XCALL-Syntax. Verwenden Sie diese Syntax für Updates und Löschungen.

  • VCALL. Verwenden Sie diese Syntax für updatierbare Abonnements. Nur zur internen Verwendung.

Jede Methode unterscheidet sich in der Datenmenge, die sie an den Abonnenten sendet. Zum Beispiel übergibt SCALL nur Werte für die Spalten, die ein Update tatsächlich beeinflusst. XCALL benötigt alle Spalten, unabhängig davon, ob ein Update sie beeinflusst oder nicht, sowie alle alten Datenwerte für jede Spalte. In vielen Fällen ist SCALL für Updates geeignet, aber wenn Ihre Anwendung alle Datenwerte während eines Updates benötigt, unterstützt XCALL diese Anforderung.

CALL-Syntax

INSERT Gespeicherte Prozeduren
Gespeicherte Prozeduren, die INSERT-Anweisungen verarbeiten, erhalten die eingefügten Werte für alle Spalten:

c1, c2, c3,... cn  

UPDATE Gespeicherte Prozeduren
Gespeicherte Prozeduren, die UPDATE-Anweisungen verarbeiten, erhalten die aktualisierten Werte für alle in dem Artikel definierten Spalten, gefolgt von den ursprünglichen Werten für die Primärschlüsselspalten. Der Prozess versucht nicht zu bestimmen, welche Spalten sich geändert haben:

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

DELETE Gespeicherte Prozeduren
Gespeicherte Prozeduren, die DELETE-Anweisungen verarbeiten, erhalten Werte für die Primärschlüsselspalten:

pkc1, pkc2, pkc3,... pkcn  

SCALL-Syntax

UPDATE Gespeicherte Prozeduren
Gespeicherte Prozeduren, die Anweisungen verarbeiten UPDATE , erhalten die aktualisierten Werte nur für jene Spalten, die sich geändert haben, gefolgt von den ursprünglichen Werten für die Primärschlüsselspalten und dann einem Bitmask-(binary(n))-Parameter, der die geänderten Spalten anzeigt. Im folgenden Beispiel änderte sich Spalte 2 (c2) nicht:

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

MCALL-Syntax

UPDATE Gespeicherte Prozeduren
Gespeicherte Prozeduren, die Anweisungen verarbeiten UPDATE , erhalten die aktualisierten Werte für alle im Artikel definierten Spalten, gefolgt von den ursprünglichen Werten für die Primärschlüsselspalten, und dann einen Bitmask-(binary(n))-Parameter, der die geänderten Spalten anzeigt:

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

XCALL-Syntax

UPDATE Gespeicherte Prozeduren
Gespeicherte Prozeduren, die UPDATE-Anweisungen verarbeiten, erhalten für alle im Artikel enthaltenen Spalten die ursprünglichen Werte (das Vorherabbild), gefolgt von den aktualisierten Werten (das Nachherabbild) für alle im Artikel enthaltenen Spalten:

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

DELETE Gespeicherte Prozeduren
Gespeicherte Prozeduren, die DELETE-Anweisungen verarbeiten, erhalten für alle im Artikel definierten Spalten die ursprünglichen Werte (die Werte vor der Änderung):

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

Hinweis

Wenn Sie XCALL verwenden, sollten die Before-Image-Werte für die Spalten text und imageNULL sein.

Beispiele

Bei den folgenden Prozeduren handelt es sich um Standardprozeduren, die für die Vendor Table in der Adventure Works-Beispieldatenbank erstellt wurden.

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