Artigos transacionais - especificar como as mudanças são propagadas

Aplica-se a:SQL ServerInstância Gerenciada de SQL do Azure

A replicação transacional permite que você especifique como as alterações de dados são propagadas do Publicador aos Assinantes. Para cada tabela publicada, você pode especificar uma das quatro maneiras pelas quais cada operação (INSERTou UPDATEDELETE) deve ser propagada para o Assinante:

  • Especifique que a replicação transacional deverá gerar script e subsequentemente chamar um procedimento armazenado para propagar alterações aos Assinantes (o padrão).

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

  • Especifique que um procedimento armazenado personalizado deverá ser usado.

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

Por padrão, a replicação transacional propaga 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 exclusão em uma tabela no Publicador, a operação é convertida em uma chamada para um procedimento armazenado no Assinante. O procedimento armazenado aceita parâmetros que mapeiam para as colunas da tabela, permitindo que essas colunas sejam alteradas no Assinante.

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

Procedimentos armazenados padrão e personalizados

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

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

  • sp_MSupd_<tablename>, que manipula atualizações.

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

O <nome> da tabela usado no procedimento depende de como você adiciona o artigo à publicação e se o banco de dados de assinaturas contém uma tabela com o mesmo nome, mas com um proprietário diferente.

Você pode substituir qualquer um desses procedimentos por um procedimento personalizado que especifica ao adicionar um artigo a uma publicação. Use os procedimentos personalizados se o seu aplicativo exigir lógica personalizada, como inserir dados em uma tabela de auditoria quando uma linha é atualizada em um Assinante. Para mais informações sobre como especificar procedimentos armazenados personalizados, consulte os artigos de instruções listados na seção anterior.

Quando você especifica os procedimentos padrão de replicação ou procedimentos personalizados, também especifica a sintaxe de chamadas para cada procedimento. A replicação seleciona a sintaxe padrão da chamada se você usar os procedimentos padrão. A sintaxe de chamada determina a estrutura dos parâmetros fornecidos para o procedimento e quanta informação é enviada ao Assinante com cada alteração de dados. Para mais informações, veja a seção "Sintaxe de Chamadas para Procedimentos Armazenados" neste artigo.

Considerações para o uso de procedimentos armazenados personalizados

Lembre-se das seguintes considerações ao usar procedimentos armazenados personalizados:

  • Você deve suportar a lógica no procedimento armazenado; A Microsoft não oferece 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 assinante geralmente é idêntico ao esquema no publicador, mas também pode ser um subconjunto do esquema do publicador se você usar filtragem por colunas. Se você precisar transformar o esquema à medida que os dados são movidos, para que o esquema no Assinante não seja um subconjunto do esquema no Editor, use o SQL Server 2019 Integration Services (SSIS). Para obter mais informações, consulte SQL Server Integration Services.

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

  • Se você usar um valor maior que 1 para o parâmetro -SubscriptionStreams do Agente de Distribuição, certifique-se de que as atualizações nas colunas-chave primárias tenham sucesso. Por exemplo:

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

    Se o Agente de Distribuição usar mais de uma conexão, essas duas atualizações podem se replicar em conexõ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 lidam com essa situação gerando um erro caso nenhuma linha seja afetada em uma atualização:

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

    Elevar o erro forçará o Agente de Distribuição a tentar novamente as atualizações em uma única conexão, que obtém êxito. Procedimentos armazenados personalizados devem incluir lógica semelhante.

Sintaxe de chamada para procedimentos armazenados

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

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

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

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

  • Sintaxe XCALL. Use essa sintaxe para atualizações e deleções.

  • VCALL. Use essa sintaxe para assinaturas atualizáveis. Somente 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 realmente afeta. O XCALL requer todas as colunas, seja uma atualização que as afete ou não, e todos os valores antigos de dados para cada coluna. Em muitos casos, o SCALL é apropriado para atualizações, mas se sua aplicação requer todos os valores de dados durante uma atualização, o XCALL suporta essa necessidade.

Sintaxe de CALL

INSERT procedimentos armazenados
Procedimentos armazenados que lidam com INSERT instruções recebem os valores inseridos para todas as colunas:

c1, c2, c3,... cn  

UPDATE procedimentos armazenados
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 de chave primária. O processo não tenta determinar quais colunas mudaram:

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

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

pkc1, pkc2, pkc3,... pkcn  

Sintaxe SCALL

UPDATE procedimentos armazenados
Procedimentos armazenados que processam instruções UPDATE recebem os valores atualizados apenas das colunas que foram alteradas, seguidos pelos valores originais das colunas da chave primária e, em seguida, por um parâmetro de máscara de bits (binary(n)) que indica quais colunas foram alteradas. No exemplo a seguir, a coluna 2 (c2) não mudou:

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

Sintaxe MCALL

UPDATE procedimentos armazenados
Procedimentos armazenados que lidam com UPDATE instruções recebem os valores atualizados para todas as colunas definidas no artigo, seguidos pelos valores originais para as colunas de chave primária, e então 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
Procedimentos armazenados que processam instruções UPDATE recebem os valores originais (a imagem anterior) de todas as colunas definidas no artigo, seguidos dos valores atualizados (a imagem posterior) de todas as colunas definidas no artigo:

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

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

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

Observação

Quando você usa XCALL, os valores da imagem anterior para as 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