Artigos transacionais - especificar como as alterações são propagadas

Aplica-se a:SQL ServerAzure SQL Managed Instance

A replicação transacional permite especificar como as alterações de dados são propagadas do Publicador para os Assinantes. Para cada tabela publicada, pode especificar uma das quatro formas como cada operação (INSERT, UPDATE, ou DELETE) deve ser propagada ao Assinante:

  • Especifique que a replicação transacional deve criar scripts e, posteriormente, chamar um procedimento armazenado para propagar alterações para Assinantes (o padrão).

  • Especifique que a alteração deve ser propagada utilizando uma instrução INSERT, UPDATE ou DELETE (a predefinição para Subscritores que não sejam do SQL Server).

  • Especifique que um procedimento armazenado personalizado deve ser usado.

  • Especifique que esta ação não deve ser executada em nenhum Assinante. As transações desse tipo não são replicadas.

Por padrão, a replicação transacional propaga as alterações para os Assinantes por meio de um conjunto de procedimentos armazenados instalados em cada Assinante. Quando ocorre uma inserção, atualização ou eliminação numa tabela no Publicador, a operação é traduzida numa chamada para um procedimento armazenado no Subscritor. O procedimento armazenado aceita parâmetros que correspondem às colunas na tabela, permitindo que essas colunas sejam alteradas em Assinante.

Para definir o método de propagação para alterações de dados em artigos transacionais, consulte Definir o método de propagação para alterações de dados para artigos transacionais.

Procedimentos armazenados padrão e personalizados

A replicação cria três procedimentos armazenados predefinidos para cada artigo da tabela:

  • sp_MSins_<tablename>, que manipula inserções.

  • sp_MSupd_<nome da tabela>, que lida com atualizações.

  • sp_MSdel_<tablename>, que manipula exclusões.

O <> utilizado no procedimento depende de como adiciona o artigo à publicação e de se a base de dados da subscrição contém uma tabela com o mesmo nome, mas um proprietário diferente.

Pode substituir qualquer um destes procedimentos por um procedimento personalizado que especifique ao adicionar um artigo a uma publicação. Use procedimentos personalizados se a sua aplicação requer lógica personalizada, como inserir dados numa tabela de auditoria quando uma linha é atualizada num Subscritor. Para mais informações sobre a especificação de procedimentos armazenados personalizados, consulte os artigos práticos listados na secção anterior.

Quando especifica os procedimentos de replicação predefinidos ou os procedimentos personalizados, especifica também a sintaxe de chamada de cada procedimento. A replicação seleciona a sintaxe padrão da chamada se usar os procedimentos padrão. A sintaxe da chamada determina a estrutura dos parâmetros fornecidos ao procedimento e a quantidade de informações que são enviadas ao Assinante a cada alteração de dados. Para mais informações, consulte a secção "Sintaxe de Chamada para Procedimentos Armazenados" neste artigo.

Considerações para a utilização de procedimentos armazenados personalizados

Tenha em mente as seguintes considerações ao usar procedimentos armazenados personalizados:

  • Deve suportar a lógica no procedimento armazenado; A Microsoft não fornece suporte para lógica personalizada.

  • Para evitar conflitos com as transações usadas pela replicação, não use transações explícitas em procedimentos personalizados.

  • O esquema no Subscritor é tipicamente idêntico ao esquema do Publisher, mas também pode ser um subconjunto do esquema do Publisher se usar filtragem por colunas. Se precisar de transformar o esquema à medida que os dados se movem para que o esquema no Subscritor não seja um subconjunto do esquema do Publisher, use o SQL Server 2019 Integration Services (SSIS). Para obter mais informações, consulte SQL Server Integration Services.

  • Se fizer alterações de esquema numa tabela publicada, regenere os procedimentos personalizados. Para obter mais informações, consulte Regenerar procedimentos transacionais personalizados para refletir alterações de estrutura.

  • Se usar um valor superior a 1 para o parâmetro -SubscriptionStreams do Distribution Agent, certifique-se de que as atualizações das colunas principais primárias têm sucesso. Por exemplo:

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

    Se o Distribution Agent usar mais do que uma ligação, estas duas atualizações podem replicar-se em ligações diferentes. Se a atualização 1 for aplicada primeiro, não há problema. Se a atualização 2 for aplicada primeiro, ela retorna 0 rows affected porque a atualização 1 ainda não aconteceu. Os procedimentos padrão tratam desta situação gerando um erro se nenhuma linha for afetada numa atualização:

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

    Gerar o erro obriga o Distribution Agent a repetir as atualizações numa única ligação, o que é bem-sucedido. Os procedimentos armazenados personalizados devem incluir lógica semelhante.

Sintaxe de chamada para procedimentos armazenados

Pode usar cinco opções diferentes de sintaxe para chamar os procedimentos que a replicação transacional utiliza:

  • Sintaxe CALL. Use esta sintaxe para inserções, atualizações e eliminações. Por padrão, a replicação usa essa sintaxe para inserções e exclusões.

  • Sintaxe SCALL. Use esta sintaxe apenas para atualizações. Por padrão, a replicação usa essa sintaxe para atualizações.

  • Sintaxe MCALL. Use esta sintaxe apenas para atualizações.

  • Sintaxe XCALL. Use esta sintaxe para atualizações e eliminações.

  • VCALL. Use esta sintaxe para subscrições atualizáveis. Apenas para uso interno.

Cada método difere na quantidade de dados que envia ao Assinante. Por exemplo, o SCALL passa valores apenas para as colunas que uma atualização afeta efetivamente. O XCALL requer todas as colunas, independentemente de uma atualização as afetar ou não, e todos os valores antigos de dados para cada coluna. Em muitos casos, o SCALL é adequado para atualizações, mas se a sua aplicação requer todos os valores de dados durante uma atualização, o XCALL suporta esta necessidade.

Sintaxe CALL

INSERT Procedimentos armazenados
Os procedimentos armazenados que processam instruções INSERT recebem os valores inseridos em todas as colunas:

c1, c2, c3,... cn  

UPDATE Procedimentos armazenados
Os procedimentos armazenados que processam instruções UPDATE recebem os valores atualizados de todas as colunas definidas no artigo, seguidos dos valores originais das colunas da chave primária. O processo não tenta determinar quais as colunas que mudaram:

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

DELETE Procedimentos armazenados
Os procedimentos armazenados que processam instruções DELETE recebem valores para as colunas da chave primária:

pkc1, pkc2, pkc3,... pkcn  

Sintaxe do SCALL

UPDATE Procedimentos armazenados
Os procedimentos armazenados que lidam com UPDATE instruções recebem os valores atualizados apenas para as colunas que mudaram, seguidos pelos valores originais para as colunas de chave primárias, e depois um parâmetro bitmask (binary(n)) que indica as colunas alteradas. No exemplo seguinte, a coluna 2 (c2) não mudou:

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

Sintaxe MCALL

UPDATE Procedimentos armazenados
Os procedimentos armazenados que lidam com UPDATE instruções recebem os valores atualizados para todas as colunas definidas no artigo, seguidos pelos valores originais das colunas da chave primária, e depois um parâmetro bitmask (binary(n)) que indica as colunas alteradas:

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

Sintaxe XCALL

UPDATE Procedimentos armazenados
Os procedimentos armazenados que processam instruções UPDATE recebem os valores originais (imagem anterior) para todas as colunas definidas no artigo, seguidos dos valores atualizados (imagem posterior) para todas as colunas definidas no artigo:

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

DELETE Procedimentos armazenados
Os procedimentos armazenados que lidam com DELETE instruções recebem os valores originais (a imagem anterior) para todas as colunas definidas no artigo:

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

Observação

Quando utiliza XCALL, os valores da imagem anterior das colunas text e image devem ser NULL.

Exemplos

Os procedimentos a seguir são os procedimentos padrão criados para o Vendor Table no banco de dados de exemplo da 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