Cómo arreglar una replicación desordenada en MS SQL Server

11

Restablecí una base de datos desde una copia de seguridad. La base de datos usa la replicación para publicar en un servidor diferente. Suponiendo que la restauración de la base de datos rompería la replicación, traté de eliminarla y volver a crearla (tenemos un script para volver a crearla desde cero). No estoy seguro de lo que hice exactamente, pero ahora está en un estado completamente desordenado y no puedo solucionarlo.

Primero, trato de deshacerme de la suscripción (en el servidor del editor):

EXEC sp_dropsubscription @publication = 'PublicationName', @article = N'all', @subscriber = 'SubscriberServerName'

Esto parece funcionar. SELECT * FROM syssubscriptionsno muestra resultados Buscando en el servidor del suscriptor, SSMS> {SubscriberServer}> Replicación> Suscripciones locales: la suscripción no está allí.

Entonces trato de eliminar la publicación. SSMS> {Servidor}> Replicación> Publicaciones locales> {PublicationName}> Eliminar. Esto da el siguiente mensaje de error:

Could not delete publication 'PublicationName'.
Could not drop article. A subscription exists on it.
Changed database context to 'DatabaseName'. (Microsoft SQL Server, Error: 14046)

Ok, entonces trato de soltar los artículos:

EXEC sp_droparticle @publication = 'PublicationName', @article = N'all'

y obtén este error:

Invalidated the existing snapshot of the publication. Run the Snapshot Agent again to generate a new snapshot.
Msg 14046, Level 16, State 1, Procedure sp_MSdrop_article, Line 75
Could not drop article. A subscription exists on it.

Ok, entonces trato de iniciar el Agente de instantáneas y obtengo esta excepción interna de SQL:

The SQL command 'sp_MSactivate_auto_sub' had returned fewer rows than expected by the replication agent.

Así que he intentado un método alternativo de borrar el artículo, DELETE FROM sysarticles. Esto parece haber funcionado: ahora me he deshecho de los artículos, pero sigo recibiendo el mismo error 'No se puede descartar la publicación porque al menos existe una suscripción para esta publicación' cuando intento eliminar la publicación.

También he reiniciado SQL Server, no ayudó.

No sé qué está pasando aquí y cómo lo soluciono.

Por cierto, esto es lo que sucede cuando le das a un desarrollador de software que sabe lo suficiente como para ser peligroso las claves de la base de datos. Afortunadamente, este no es un entorno de producción ...

Chico alto
fuente

Respuestas:

10

TLDR:

Parece que deshabilitar y volver a habilitar la replicación probablemente solucionó el problema:

exec sp_replicationdboption @dbname = N'DatabaseName', @optname = N'publish', @value = N'false'
exec sp_replicationdboption @dbname = N'DatabaseName', @optname = N'publish', @value = N'true'

Supongo que esto es equivalente a apagarlo y volver a encenderlo ...

Versión más larga:

Un compañero de trabajo trató de arreglarlo. Intentó algunas cosas pero no llegó muy lejos. El único cambio que hizo antes de darse por vencido fue desactivar la replicación.

Entonces probé la sugerencia de Cody . El comando sp_dropsubscription se quejó de que no existen suscripciones. Así que probé el comando sp_droppublication. Esto se quejó de que la replicación no estaba habilitada en la base de datos. Entonces lo habilité y volví a ejecutar el comando. Esta vez se quejó de que la publicación no existía. Actualicé el nodo Publicaciones locales en SSMS y, efectivamente, se había ido. Ejecuté el script de configuración de replicación, generé una nueva instantánea y ahora todo funciona correctamente. ¡Alegría!

No estoy 100% seguro de que deshabilitar y habilitar la replicación sea lo que realmente solucionó el problema, pero definitivamente vale la pena intentarlo si la replicación se estropea.

Chico alto
fuente
Gran lectura para novatos. ¿Es seguro decir que primero debe desactivar la replicación antes de restaurar la base de datos?
Keith Rivera el
Ciertamente voy a intentar eso la próxima vez: por lo que he leído, la replicación no debería tener que ser completamente impresionado y recreado (como inicialmente pensé que sería). Deshabilite la replicación, restaure la base de datos, habilite la replicación, inserte una nueva instantánea. Mientras los artículos sigan siendo válidos, debería ser bueno. Vale la pena intentarlo de todos modos ...
TallGuy
Replicación total novato aquí, pero siguiendo el TLDR; Las instrucciones han llevado a la desaparición de mis publicaciones de SSMS. Las consultas MSPublicationsen la distributionbase de datos revelan que la publicación ya no existe. ¿Se espera esto?
pimbrouwers
5

Tuve un lío con la replicación y lo resolví con esto

DECLARE @subscriptionDB AS sysname
SET @subscriptionDB = N'DBName'

-- Remove replication objects from a subscription database (if necessary).
USE master
EXEC sp_removedbreplication @subscriptionDB
GO 

Eso y:

exec sp_cleanupdbreplication

Son los salvadores cuando se limpian las replicaciones desordenadas.

Guillermo Zooby
fuente
1
Creo que su publicación me salvó de volver a configurar mi entorno de prueba. No estoy seguro de qué comando anterior lo hizo, pero ahora puedo eliminar índices sin el error de que se publiquen para la replicación. Muchas gracias a ti.
MHSQLDBA
2

Restaurar la base de datos interrumpirá la replicación, así que eso es normal. Además, la mayoría de los otros mensajes de error son solo seguimientos porque no ha podido eliminar todas las suscripciones (o al menos SQL cree que sí).

Sabe que tiene su editor (la base de datos de origen) y al menos un suscriptor (la base de datos de destino), y que estos son dos servidores diferentes. Solo quiero mencionar que también hay un distribuidor que está en cualquiera de estos servidores u otro, y probablemente en una base de datos llamada distribución. A veces tiene información útil y otras cosas se caen porque la información entre los tres no coincide.

De todos modos, cuando revisó los suscriptores, ¿también revisó esa sección en el servidor del editor para asegurarse de que no hubiera nada más en la lista? Si encuentra alguno, puede intentar eliminarlo manualmente:

exec sp_dropsubscription @publication = N'xxx', @subscriber = N'xxx', @destination_db = N'xxx', @article = N'all'
-- And if that doesn't work
exec sp_dropsubscription @publication = N'xxx', @subscriber = N'xxx', @destination_db = N'xxx', @article = N'all', @Ignore_Distributor = 1

Pero suponiendo que realmente se hayan ido, intente esto en la base de datos del editor:

exec sp_droppublication @publication = N'xxx'
-- And if that doesn't work
exec sp_droppublication @publication = N'xxx', @Ignore_Distributor = 1

Háganos saber cómo va. La replicación cuando entra en este estado me confunde a mí y a otros buenos DBA nada que ver con ser un desarrollador en absoluto :-)

Cody Konior
fuente
Gracias por la sugerencia. El comando sp_dropsubscription se quejó de que no existen suscripciones. El comando sp_droppublication se quejó de que la replicación no estaba habilitada, lo que me llevó a lo que parece ser la solución.
TallGuy
Para mí, el comando sp_removedbreplication funcionó la mayor parte del tiempo cada vez que tuve que eliminar con fuerza la replicación.
SQLPRODDBA
0

La única forma en que he podido deshacerme de los artefactos de replicación fantasma es soltando las suscripciones, artículos y publicaciones. Si todavía hay suscripciones fantasmas, vuelva a crear la publicación, incluido el suscriptor fantasma. Esto parece funcionar especialmente con versiones anteriores.

Edwina Montague-Martin
fuente
0

Esto es lo que hago normalmente cuando tengo una publicación que está en mal estado.

Es un poco feo, pero me ha funcionado en muchas ocasiones en diferentes entornos. ¿Qué lo causa? esto es a veces difícil de averiguar, a veces es mejor que empezar de cero, pero incluso para eso se necesita para aclarar allla residualsde la publicación actual que es defectuoso.

solo para ponerlo en contexto:

Esto es lo que veo desde el monitor de replicación:

ingrese la descripción de la imagen aquí

y cuando uso mi propio monitor de replicación usando T-SQL :

DECLARE @cmd NVARCHAR(max)
DECLARE @publisher SYSNAME, @publisher_db SYSNAME, @publication SYSNAME, @pubtype INT
DECLARE @subscriber SYSNAME, @subscriber_db SYSNAME, @subtype INT
DECLARE @cmdcount INT, @processtime INT
DECLARE @ParmDefinition NVARCHAR(500)
DECLARE @JobName SYSNAME
DECLARE @minutes INT, @threshold INT, @maxCommands INT, @mail CHAR(1) = 'N'
SET @minutes = 60 --> Define how many minutes latency before you would like to be notified
SET @maxCommands = 80000  --->  change this to represent the max number of outstanding commands to be proceduresed before notification
SET @threshold = @minutes * 60

IF OBJECT_ID ('TEMPDB..#Replication_Qu_History')  IS NOT NULL
   DROP TABLE #Replication_Qu_History

IF OBJECT_ID ('TEMPDB..##PublicationInfo')  IS NOT NULL
   DROP TABLE  ##PublicationInfo

IF OBJECT_ID ('TEMPDB..#PublisherInfo')  IS NOT NULL
   DROP TABLE  #PublisherInfo

IF OBJECT_ID ('TEMPDB..##SubscriptionInfo')  IS NOT NULL
   DROP TABLE  ##SubscriptionInfo

SELECT * INTO #PublisherInfo
FROM OPENROWSET('SQLOLEDB', 'SERVER=(LOCAL);TRUSTED_CONNECTION=YES;'
, 'SET FMTONLY OFF EXEC distribution.dbo.sp_replmonitorhelppublisher')

SELECT @publisher = publisher FROM #PublisherInfo     

SET @cmd = 'SELECT * INTO ##PublicationInfo FROM OPENROWSET(''SQLOLEDB'',''SERVER=(LOCAL);TRUSTED_CONNECTION=YES''
,''SET FMTONLY OFF EXEC distribution.dbo.sp_replmonitorhelppublication @publisher='
+ @publisher + ''')'
--select @cmd
EXEC sp_executesql @cmd

SELECT @publisher_db=publisher_db, @publication=publication, @pubtype=publication_type  FROM ##PublicationInfo

SET @cmd = 'SELECT * INTO ##SubscriptionInfo FROM OPENROWSET(''SQLOLEDB'',''SERVER=(LOCAL);TRUSTED_CONNECTION=YES''
,''SET FMTONLY OFF EXEC distribution.dbo.sp_replmonitorhelpsubscription @publisher='
+ @publisher + ',@publication_type=' + CONVERT(CHAR(1),@pubtype) + ''')'
--select @cmd
EXEC sp_executesql @cmd


ALTER TABLE ##SubscriptionInfo
ADD  PendingCmdCount INT NULL,
EstimatedProcessTime INT NULL


SELECT *
FROM #PublisherInfo

SELECT *
FROM ##SubscriptionInfo 

SELECT *
FROM ##PublicationInfo 

puedes ver 2 líneas en el último cuadro a continuación, y una no debería estar allí:

ingrese la descripción de la imagen aquí

lo mismo cuando uso este script:

EXEC distribution.dbo.sp_replmonitorhelppublication @publisher='my publisher'

ingrese la descripción de la imagen aquí

Primero, haga lo que se muestra en las otras respuestas anteriores, si eso funciona , está bien, a veces funciona, el problema está resuelto.

eso sería más o menos:

exec master.dbo.sp_replicationdboption @dbname = 'my_PUBLICATION', @optname = N'publish', @value = N'false'
exec master.dbo.sp_replicationdboption @dbname = 'my_PUBLICATION', @optname = N'publish', @value = N'true'

sp_droppublication @publication='my_PUBLICATION'

-- Remove replication objects from a subscription database (if necessary).
exec master.dbo.sp_removedbreplication 'my_PUBLICATION'

exec master.dbo.sp_removedbreplication 'my_PUBLICATION'

use my_PUBLICATION

sp_removedbreplication @type='both'


USE [master]
EXEC sp_replicationdboption 
  @dbname = N'my_PUBLICATION', 
  @optname = N'publish', 
  @value = N'false';
GO


EXEC distribution.dbo.sp_replmonitorhelppublication @publisher='PUBLISHER_SERVER'

sp_replmonitorhelppublisher @publisher='PUBLISHER_SERVER'

DECLARE @publicationDB AS sysname;
DECLARE @publication AS sysname;
SET @publicationDB = N'my_PUBLICATION'; 
SET @publication = N'my_PUBLICATION'; 

-- Remove a transactional publication.
USE my_PUBLICATION
EXEC sp_droppublication @publication = @publication;

-- Remove replication objects from the database.
USE [master]
EXEC sp_replicationdboption 
  @dbname = @publicationDB, 
  @optname = N'publish', 
  @value = N'false';
GO

Ahora, para deshacernos por completo de esta publicación, comenzaremos conectándonos al buscriber, y luego al editor, y luego al distribuidor según el script a continuación:

-- Connect Subscriber
:connect [SUBSCRIBER_SERVER]
use [master]
exec sp_helpreplicationdboption @dbname = N'SUBSCRIBER_DATABASE'
go
use [SUBSCRIBER_DATABASE]
exec sp_subscription_cleanup @publisher = N'PUBLISHER_SERVER', @publisher_db = N'my_PUBLICATION_DB', 
@publication = N'my_PUBLICATION'
go


-- Connect Publisher Server
:connect [PUBLISHER_SERVER]
-- Drop Subscription
use [my_PUBLICATION]
exec sp_dropsubscription @publication = N'my_PUBLICATION', @subscriber = N'all', 
@destination_db = N'SUBSCRIBER_DATABASE', @article = N'all'
go
-- Drop publication
exec sp_droppublication @publication = N'my_PUBLICATION'
-- Disable replication db option
exec sp_replicationdboption @dbname = N'my_PUBLICATION_db', @optname = N'publish', @value = N'false'
GO

-- Connect Distributor
:CONNECT [PUBLISHER_SERVER]
go

exec Distribution.dbo.sp_MSremove_published_jobs @server = 'PUBLISHER_SERVER', 
@database = N'my_PUBLICATION'
go

--===========================================================================================
--THAT DOES NOT GENERALLY GET RID OF THE JOBS FOR YOU
-- so you need to find them using these selects, and get rid of them manually yourself:

--select * from Distribution.dbo.MSpublications
--select * from Distribution.dbo.MSpublications
--===========================================================================================


select * from Distribution.[dbo].[MSlogreader_agents]
where publisher_db = N'my_PUBLICATION'

--found 1 job:
--PUBLISHER_SERVER-my_PUBLICATION-11

--script the job
--script the job delete script - and run that - keeping the job creation script just in case
exec msdb.dbo.sp_help_job @job_id=0x93C63D34E357704B818312B93FCA02FB
exec msdb.dbo.sp_delete_job @job_id=0x93C63D34E357704B818312B93FCA02FB



select * from Distribution.[dbo].[MSdistribution_agents]
where publisher_db = N'my_PUBLICATION'

--here found 2 jobs:

--PUBLISHER_SERVER-my_PUBLICATION-my_PUBLICATION--67
--PUBLISHER_SERVER-my_PUBLICATION-my_PUBLICATION--68


--here is the problem - it cannot find the jobs, the jobs are not even there anymore, one of those things
exec msdb.dbo.sp_delete_job @job_id=0x0F1564BAACD5464C988DE8957C25C411
exec msdb.dbo.sp_delete_job @job_id=0x6215C40F999CE248A30EE735E2C0E59D

--Msg 14262, Level 16, State 1, Procedure sp_verify_job_identifiers, Line 41 [Batch Start Line 52]
--The specified @job_id ('BA64150F-D5AC-4C46-988D-E8957C25C411') does not exist.


--Msg 14262, Level 16, State 1, Procedure sp_verify_job_identifiers, Line 41 [Batch Start Line 53]
--The specified @job_id ('0FC41562-9C99-48E2-A30E-E735E2C0E59D') does not exist.

exec msdb.dbo.sp_delete_job @job_name='PUBLISHER_SERVER-my_PUBLICATION-my_PUBLICATION'
PUBLISHER_SERVER-my_PUBLICATION-my_PUBLICATION--68

en este punto, vuelva a crear la publicación como lo haría normalmente

luego ponga la instantánea para ejecutar

espere a que termine de generar la instantánea

MAYBE YOU DONT NEED TO RUN THE SNAP- intente withoutejecutarlo primero, la mayoría de las veces funciona, también puede agregar solo 1-2 smallartículos a la publicación para que el complemento se ejecute rápidamente

pero si ejecuta la instantánea, debe esperar hasta que finalice antes de poder continuar con el siguiente paso: drop the publication

ingrese la descripción de la imagen aquí

después de eso, genera los scripts drop that publicationsegún la imagen a continuación: ingrese la descripción de la imagen aquí

después de eso, con suerte, cuando ejecute nuestros scripts originales anteriores , o eche un vistazo al monitor de replicación, no verá la publicación defectuosa, solo las buenas, en mi caso solo una:

ingrese la descripción de la imagen aquí

Marcello Miorelli
fuente
-1

Tuve el mismo problema en mi cuadro de preproducción, el comando

exec sp_cleanupdbreplication

parece haber trabajado en la limpieza de entradas de suscripción falsas ...

CARLA
fuente