Come risolvere una replica incasinata su MS SQL Server


11

Ho ripristinato un database da un backup. Il database utilizza la replica per pubblicare su un altro server. Supponendo che il ripristino del database interrompesse la replica, ho cercato di eliminare la replica e ricrearla (abbiamo uno script per ricrearla da zero). Non sono sicuro di quello che ho fatto, ma ora è completamente incasinato e non posso ripararlo.

Innanzitutto, provo a eliminare l'abbonamento (sul server del publisher):

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

Questo sembra funzionare. SELECT * FROM syssubscriptionsnon mostra risultati. Guardando sul server abbonati, SSMS> {SubscriberServer}> Replica> Abbonamenti locali - l'abbonamento non è presente.

Quindi provo a cancellare la pubblicazione. SSMS> {Server}> Replica> Pubblicazioni locali> {PublicationName}> Elimina. Questo dà il seguente messaggio di errore:

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, quindi provo a rilasciare gli articoli:

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

e ottieni questo errore:

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, quindi provo ad avviare Snapshot Agent e ottengo questa eccezione SQL interna:

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

Così ho cercato un metodo alternativo di cancellare l'articolo, DELETE FROM sysarticles. Questo sembra aver funzionato - ora mi sono liberato degli articoli, ma ottengo sempre lo stesso errore "Impossibile eliminare la pubblicazione perché esiste almeno un abbonamento per questa pubblicazione" quando provo a eliminare la pubblicazione.

Ho anche riavviato SQL Server - non ha aiutato.

Non so cosa sta succedendo qui e come posso risolverlo?

A proposito, questo è ciò che accade quando dai a uno sviluppatore di software che sa quanto basta per essere pericolose le chiavi del database. Fortunatamente, questo non è un ambiente di produzione ...

Risposte:


10

TLDR:

Sembra che disabilitare e riattivare la replica probabilmente risolva il 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'

Immagino che questo equivalga a spegnerlo e poi riaccenderlo ...

Versione più lunga:

Un compagno di lavoro ha provato a risolvere il problema. Ha provato alcune cose ma non è andato molto lontano. L'unica modifica apportata prima di rinunciare è stata la disabilitazione della replica.

Ho quindi provato il suggerimento di Cody . Il comando sp_dropsubscription si è lamentato del fatto che non esistano abbonamenti. Quindi ho provato il comando sp_droppublication. Ciò si è lamentato del fatto che la replica non era abilitata sul database. Quindi l'ho abilitato e ho eseguito nuovamente il comando. Questa volta si è lamentato del fatto che la pubblicazione non esistesse. Ho aggiornato il nodo Pubblicazioni locali in SSMS e sicuramente era andato. Ho eseguito lo script di configurazione della replica, ho generato una nuova istantanea e ora tutto funziona correttamente. Gioia!

Non sono sicuro al 100% che disabilitare e abilitare la replica sia ciò che ha effettivamente risolto il problema, ma vale sicuramente la pena provare se la replica viene incasinata.


Ottima lettura per i neofiti. È sicuro dire che è necessario disabilitare la replica prima di ripristinare il database?
Keith Rivera,

Lo proverò sicuramente la prossima volta - da quello che ho letto la replica non dovrebbe essere completamente spazzata via e ricreata (come inizialmente pensavo che avrebbe fatto). Disabilitare la replica, ripristinare il database, abilitare la replica, inviare una nuova istantanea. Finché gli articoli sono ancora validi, dovrebbe essere buono andare. Vale comunque la pena provare ...
TallGuy

Newbie di replica totale qui, ma seguendo il TLDR; le istruzioni hanno portato alla scomparsa delle mie pubblicazioni da SSMS. Le query MSPublicationsnel distributiondatabase rivelano che la pubblicazione è effettivamente sparita. È previsto?
pimbrouwers,

5

Ho avuto un pasticcio con la replica e l'ho risolto con questo

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

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

Quello e:

exec sp_cleanupdbreplication

Sono i salvatori quando ripuliscono le repliche incasinate.


1
Credo che il tuo post mi abbia appena salvato dalla riconfigurazione del mio ambiente di test. Non sono sicuro di quale comando sopra sia stato eseguito, ma ora posso eliminare gli indici senza che l'errore venga pubblicato per la replica. Molte grazie a te.
MHSQLDBA

2

Il ripristino del database interromperà la replica, quindi è normale. Inoltre, la maggior parte degli altri messaggi di errore sono semplicemente seguiti perché non sei stato in grado di rimuovere tutti gli abbonamenti (o almeno SQL lo pensa).

Sai di avere il tuo editore (il database di origine) e almeno un abbonato (il database di destinazione) e che si tratta di due server diversi. Voglio solo ricordare che c'è anche un distributore che si trova su uno di questi server o su un altro, e probabilmente in un database chiamato distribuzione. A volte ha alcune informazioni utili lì dentro e a volte le cose cadono perché le informazioni tra i tre non corrispondono.

Ad ogni modo, quando hai controllato gli abbonati, hai controllato anche quella sezione sul server del publisher per assicurarti che non ci fosse nient'altro elencato? Se ne trovi qualcuno, puoi provare a rimuoverlo 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

Ma supponendo che siano davvero andati tutti, prova questo sul database del publisher:

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

Fateci sapere come va. La replica quando entra in questo stato confonde me e altri buoni DBA che non hanno niente a che fare con l'essere uno sviluppatore :-)


Grazie per il suggerimento Il comando sp_dropsubscription si è lamentato della mancanza di abbonamenti. Il comando sp_droppublication si è lamentato del fatto che la replica non era abilitata, il che mi ha portato a quella che sembra essere la soluzione.
TallGuy

Per me, il comando sp_removedbreplication ha funzionato per la maggior parte del tempo ogni volta che dovevo rimuovere forzatamente la replica.
SQLPRODDBA

0

L'unico modo in cui sono stato in grado di sbarazzarmi di artefatti di replica fantasma è quello di eliminare abbonamenti, articoli, pubblicazioni. Se ci sono ancora abbonamenti fantasma, ricrea la pubblicazione incluso l'abbonato fantasma. Questo sembra funzionare soprattutto con le versioni precedenti.


0

questo è ciò che faccio normalmente quando ho una pubblicazione incasinata.

è un po 'brutto ma ha funzionato per me in molte occasioni in ambienti diversi. cosa lo provoca? che a volte è difficile da capire, meglio a volte è quella di ripartire da zero, ma anche per questo è necessario per chiarire allla residualsdalla pubblicazione corrente è difettoso.

solo per metterlo nel contesto:

Questo è ciò che vedo dal monitor di replica:

inserisci qui la descrizione dell'immagine

e quando uso il mio monitor di replica 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 

puoi vedere 2 righe nell'ultima casella in basso - e una non dovrebbe essere lì:

inserisci qui la descrizione dell'immagine

lo stesso quando uso questo script:

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

inserisci qui la descrizione dell'immagine

Prima fai quello che è mostrato nelle altre risposte sopra, se funziona , va bene, a volte funziona, il problema è stato risolto.

sarebbe più o meno:

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

Ora per sbarazzarci completamente di questa pubblicazione inizieremo collegandoci al buscriber, quindi all'editore e quindi al distributore secondo lo script seguente:

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

a questo punto ricreare la pubblicazione come faresti normalmente

quindi esegui l'istantanea

attendere che finisca di generare l'istantanea

MAYBE YOU DONT NEED TO RUN THE SNAP- prova a withouteseguirlo per primo, il più delle volte funziona, inoltre puoi aggiungere solo 1-2 smallarticoli alla pubblicazione in modo che lo snap venga eseguito rapidamente

ma se esegui l'istantanea, devi attendere fino al termine prima di poter passare al passaggio successivo: drop the publication

inserisci qui la descrizione dell'immagine

dopo di che si generano gli script drop that publicationsecondo l'immagine qui sotto: inserisci qui la descrizione dell'immagine

dopodiché si spera che, quando esegui i nostri script originali sopra , o dai un'occhiata al monitor di replica, non vedrai la pubblicazione difettosa, solo quelli buoni, nel mio caso solo uno:

inserisci qui la descrizione dell'immagine


-1

Ho avuto lo stesso problema sulla mia scatola di pre-produzione, il comando

exec sp_cleanupdbreplication

sembra aver lavorato alla pulizia delle voci di abbonamento fasullo ...

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.