Artykuły transakcyjne – określ, jak zmiany są propagowane

Dotyczy:programu SQL ServerAzure SQL Managed Instance

Replikacja transakcyjna umożliwia określenie, w jaki sposób zmiany danych są propagowane z wydawcy do subskrybentów. Dla każdej opublikowanej tabeli można określić jeden z czterech sposobów propagacji każdej operacji (INSERT, UPDATElub DELETE) do subskrybenta:

  • Określ, że replikacja transakcyjna powinna spowodować utworzenie skryptu, a następnie wywołanie procedury składowanej w celu propagowania zmian do subskrybentów (ustawienie domyślne).

  • Określa, że zmiana powinna być propagowana przy użyciu instrukcji INSERT, UPDATE lub DELETE (wartość domyślna dla subskrybentów innych niż SQL Server).

  • Określ, że należy użyć niestandardowej procedury przechowywanej.

  • Określ, że ta akcja nie powinna być wykonywana w żadnym subskrybencie. Transakcje tego typu nie są replikowane.

Domyślnie replikacja transakcyjna propaguje zmiany do subskrybentów za pomocą zestawu procedur składowanych zainstalowanych na każdym subskrybencie. W przypadku wystąpienia wstawiania, aktualizowania lub usuwania w tabeli u Wydawcy, operacja jest tłumaczona na wywołanie procedury składowanej u Subskrybenta. Procedura składowana akceptuje parametry, które są mapowane na kolumny w tabeli, co pozwala na zmianę tych kolumn u subskrybenta.

Aby ustawić metodę propagacji zmian danych w artykułach transakcyjnych, zobacz Set the Propagation Method for Data Changes to Transactional Articles.

Domyślne i niestandardowe procedury składowane

Replikacja tworzy trzy domyślne procedury przechowywane dla każdego artykułu tabelowego:

  • sp_MSins_<nazwa_tabeli>, która obsługuje wstawki.

  • sp_MSupd_<nazwa_tabeli>, która obsługuje aktualizacje.

  • sp_MSdel_<nazwa_tabeli>, która obsługuje usuwanie.

Nazwa >tabeli użyta < w procedurze zależy od sposobu dodania artykułu do publikacji oraz od tego, czy baza subskrypcyjna zawiera tabelę o tej samej nazwie, ale innym właścicielu.

Możesz zastąpić dowolną z tych procedur niestandardową procedurą, którą określasz przy dodawaniu artykułu do publikacji. Używaj procedur niestandardowych, jeśli Twoja aplikacja wymaga niestandardowej logiki, na przykład wstawiaj dane do tabeli audytu, gdy wiersz jest aktualizowany na poziomie Subscriber. Więcej informacji na temat określania niestandardowych procedur przechowywanych można znaleźć w artykułach instruktażowych wymienionych w poprzedniej sekcji.

Gdy określasz domyślne procedury replikacji lub procedury niestandardowe, określasz także składnię wywołań dla każdej procedury. Replikacja wybiera domyślną składnię wywołań, jeśli używasz procedur domyślnych. Składnia wywołania określa strukturę parametrów podanych w procedurze i ilość informacji wysyłanych do subskrybenta z każdą zmianą danych. Więcej informacji można znaleźć w sekcji "Składnia wywołań dla procedur przechowywanych" w tym artykule.

Rozważania dotyczące stosowania niestandardowych procedur przechowywanych

Podczas korzystania z niestandardowych procedur składowanych należy wziąć pod uwagę następujące kwestie:

  • Musisz wspierać logikę w procedurze przechowywanej; Microsoft nie zapewnia wsparcia dla logiki niestandardowej.

  • Aby uniknąć konfliktów z transakcjami używanymi przez replikację, nie używaj jawnych transakcji we własnych procedurach.

  • Schemat w Subscriber jest zazwyczaj identyczny z schematem w Publisher, ale może też być podzbiorem schematu Publisher, jeśli używasz filtrowania kolumnowego. Jeśli musisz przekształcić schemat w miarę przemieszczania się danych, tak aby schemat na Subscriber nie był podzbiorem schematu na Publisher, użyj SQL Server 2019 Integration Services (SSIS). Aby uzyskać więcej informacji, zobacz SQL Server Integration Services.

  • Jeśli wprowadzisz zmiany schematu w opublikowanej tabeli, wygeneruj ponownie procedury niestandardowe. Aby uzyskać więcej informacji, zobacz Ponowne generowanie niestandardowych procedur transakcyjnych w celu odzwierciedlenia zmian schematu.

  • Jeśli użyjesz wartości większej niż 1 dla parametru -SubscriptionStreams w Distribution Agent, upewnij się, że aktualizacje kolumn klucza głównego zakończą się sukcesem. Na przykład:

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

    Jeśli Distribution Agent używa więcej niż jednego połączenia, te dwie aktualizacje mogą się powtórzyć na różnych połączeniach. Jeśli najpierw zostanie zastosowana aktualizacja 1, nie ma problemu. Jeśli najpierw zostanie zastosowana aktualizacja 2, zwraca 0 rows affected, ponieważ aktualizacja 1 nie została jeszcze zastosowana. Domyślne procedury radzą sobie z tą sytuacją, wywołując błąd, jeśli żadne wiersze nie są dotknięte podczas aktualizacji:

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

    Wygenerowanie błędu zmusza Agenta dystrybucji do ponowienia próby zastosowania aktualizacji przy użyciu jednego połączenia, co kończy się powodzeniem. Niestandardowe procedury składowane muszą zawierać podobną logikę.

Wywoływanie składni procedur składowanych

Możesz użyć pięciu różnych opcji składni, aby nazwać procedury wykorzystywane przez replikację transakcyjną:

  • Składnia WYWOŁANIA. Używaj tej składni do wstawiania, aktualizacji i usuwania. Domyślnie replikacja używa tej składni do wstawiania i usuwania.

  • Składnia SCALL. Używaj tej składni tylko do aktualizacji. Domyślnie replikacja używa tej składni do aktualizacji.

  • Składnia MCALL. Używaj tej składni tylko do aktualizacji.

  • Składnia XCALL. Używaj tej składni do aktualizacji i usuwania.

  • VCALL. Użyj tej składni do aktualizacji subskrypcji. Tylko do użytku wewnętrznego.

Każda metoda różni się ilością danych wysyłanych do Subskrybenta. Na przykład SCALL przekazuje wartości tylko dla kolumn, na które faktycznie wpływa aktualizacja. XCALL wymaga wszystkich kolumn, niezależnie od tego, czy aktualizacja ich dotyczy, czy nie, oraz wszystkich starych wartości danych dla każdej kolumny. W wielu przypadkach SCALL jest odpowiedni dla aktualizacji, ale jeśli Twoja aplikacja wymaga wszystkich wartości danych podczas aktualizacji, XCALL wspiera tę potrzebę.

Składnia WYWOŁANIA

INSERT procedury składowane
Procedury przechowywane obsługujące INSERT instrukcje otrzymują wartości wstawione dla wszystkich kolumn:

c1, c2, c3,... cn  

UPDATE procedury składowane
Procedury przechowywane obsługujące UPDATE instrukcje otrzymują zaktualizowane wartości dla wszystkich kolumn zdefiniowanych w artykule, a następnie oryginalne wartości dla kolumn klucza głównego. Proces nie próbuje ustalić, które kolumny się zmieniły:

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

DELETE procedury składowane
Procedury przechowywane obsługujące instrukcje DELETE otrzymują wartości kolumn klucza głównego:

pkc1, pkc2, pkc3,... pkcn  

Składnia SCALL

UPDATE procedury składowane
Procedury przechowywane obsługujące UPDATE instrukcje otrzymują zaktualizowane wartości tylko dla tych kolumn, które się zmieniły, następnie oryginalne wartości dla kolumn klucza głównego, a następnie parametr bitmask (binary(n)) wskazujący zmienione kolumny. W następującym przykładzie kolumna 2 (c2) nie uległa zmianie:

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

Składnia MCALL

UPDATE procedury składowane
Procedury przechowywane obsługujące UPDATE instrukcje otrzymują zaktualizowane wartości dla wszystkich kolumn zdefiniowanych w artykule, następnie oryginalne wartości dla kolumn klucza głównego, a następnie parametr bitmask (binary(n)) wskazujący zmienione kolumny:

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

Składnia XCALL

UPDATE procedury składowane
Procedury przechowywane obsługujące UPDATE instrukcje otrzymują oryginalne wartości (obraz przed) dla wszystkich kolumn zdefiniowanych w artykule, a następnie zaktualizowane wartości (obraz po) dla wszystkich kolumn zdefiniowanych w artykule:

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

DELETE procedury składowane
Procedury składowane, które obsługują instrukcje DELETE, otrzymują oryginalne wartości (stan sprzed zmiany) dla wszystkich kolumn zdefiniowanych w artykule:

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

Notatka

Gdy używasz XCALL, wartości obrazu sprzed zmiany dla kolumn text i image powinny być równe NULL.

Przykłady

Poniższe procedury to domyślne procedury utworzone dla Vendor Table w przykładowej bazie danych firmy Adventure Works.

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