Replicação Transacional – Erro 20598 – Linha não Encontrada no Assinante

Olá pessoal,

Vamos falar de um erro bem peculiar em uma replicação transacional.

Aparece o seguinte erro “20598” no replication monitor em uma assinatura com a seguinte descrição: “The row was not found at the Subscriber when applying the replicated command.

O erro acima diz que o registro não foi encontrado no assinante quando tentou aplicar um comando que veio do publicador. Este problema  gera uma fila de comandos de delete ou update, que ficarão aguardando com erro até que seja solucionado.

Breve Explicação

Quando se adiciona um novo assinante a uma publicação, a replicação cria basicamente três stored procedures de escrita no banco assinante para cada artigo do publicador:

  • sp_MSupd_NomeArtigo
  • sp_MSdel_NomeArtigo
  • sp_MSins_NomeArtigo

Um erro de um artigo numa replicação, implica no enfileiramento dos comandos de todos os artigos pertencentes a publicação.

Mão na Massa

Voltando ao erro 20598, vamos abordar a solução deste problema em dois cenários:

  • Erros de UPDATE (sp_MSupd_NomeArtigo)
  • Erros de DELETE (sp_MSdel_NomeArtigo)

Erros de UPDATE (sp_MSupd_NomeArtigo)

A correção de comandos de update do erro 20598 é mais complexa, pois será necessário inserir o registro no assinante para que a fila de comandos flua novamente. Serão necessários três passos para pegar o registro problemático:

1° passo (pegar o xact_seqno e command_id)

Segue abaixo a forma de obter o xact_seqno e command_id via replication monitor:

Erro_Replication_Monitor_01

Erro_Replication_Monitor_02

Segue abaixo a forma de obter o xact_seqno e command_id via t-sql no banco distribution:

Erro_Na_Tabela

use distribution
go
select top 1 xact_seqno,
command_id,
error_text,
time
from dbo.msrepl_errors
where error_code <> ''
and convert(varchar(1000),error_text) = 'the row was not found at the subscriber when applying the replicated command.'
order by time desc

2° passo (pegar o publisher_database_id)

SELECT DISTINCT subscriptions.publisher_database_id
FROM sys.servers AS [publishers]
INNER JOIN distribution.dbo.MSpublications AS [publications] ON publishers.server_id = publications.publisher_id
INNER JOIN distribution.dbo.MSarticles AS [articles] ON publications.publication_id = articles.publication_id
INNER JOIN distribution.dbo.MSsubscriptions AS [subscriptions] ON articles.article_id = subscriptions.article_id AND articles.publication_id = subscriptions.publication_id AND articles.publisher_db = subscriptions.publisher_db AND articles.publisher_id = subscriptions.publisher_id
INNER JOIN sys.servers AS [subscribers] ON subscriptions.subscriber_id = subscribers.server_id
WHERE
/*Instância Publicador*/publishers.name = 'NomeInstancia_Publicador'
/*Nome da Publicação*/ AND publications.publication = 'NomeDaPublicacao'
/*Instância Assinante*/AND subscribers.name = 'NomeInstancia_Assinante'

Database_id

3° passo (executar a sp_browsereplcmds com os parâmetros dos passos anteriores)

EXECUTE distribution.dbo.sp_browsereplcmds
@xact_seqno_start = '0x00007E600000035D0015',
@xact_seqno_end = '0x00007E600000035D0015',
@publisher_database_id = 2,
@command_id = 21

distribution

Após obter os comandos da procedure de update sp_MSupd_NomeArtigo”  faça os seguintes passos:

  •  Verifique a chave da tabela NomeArtigo.
  • Faça a consulta via t-sql no banco publicador com a chave dos dados obtidos na coluna command da procedure dbo.sp_browsereplcmds.
  • Pegue o registro obtido da consulta  e leve para o banco assinante de forma manual.

Erros de DELETE (sp_MSdel_NomeArtigo)

A correção de comandos de delete do erro 20598, será necessário alterar a procedure sp_MSdel_NomeArtigo com uma condição após o begin, para que seja feito um skip do erro:


USE [BancoAssinante]
GO
ALTER procedure [dbo].[sp_MSdel_NomeArtigo]
@pkc1 int,
@pkc2 smallint,
@pkc3 char(2)
as
begin

------------------------------------------------>>>>>>>>>>>>>>>>>>>>>
--Após o begin colocar a condição abaixo para resolver
--os comandos de DELETE:

if not exists (select * from [dbo].[NomeArtigo]
where [CHAVE_01] = @pkc1 and [CHAVE_02] = @pkc2 and [CHAVE_03] = @pkc3 )
return
------------------------------------------------<<<<<<<<<<<<<<<<<<<<<<

delete [dbo].[NomeArtigo]
where [CHAVE_01] = @pkc1
and [CHAVE_02] = @pkc2
and [CHAVE_03] = @pkc3
if @@rowcount = 0
if @@microsoftversion>0x07320000
exec sp_MSreplraiserror 20598
end

OBS.: É de suma importância que se respeite a chave para não evitar problemas de integridade dos dados.

OBS2.: Para obter o nome da procedure sp_MSdel_NomeArtigo será necessário seguir os passos dos “Erros de UPDATE”, porém para a correção será necessário alterar o objeto conforme descrito acima. 

Pessoal esse é um assunto bastante complexo, espero que possa ter ajudado alguém de alguma forma.

Valeu!

God bless all!!!!

 

 

Anúncios

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair /  Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair /  Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair /  Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair /  Alterar )

Conectando a %s