Comment réparer une réplication foirée sur MS SQL Server

11

J'ai restauré une base de données à partir d'une sauvegarde. La base de données utilise la réplication pour publier sur un autre serveur. En supposant que la restauration de la base de données interromprait la réplication, j'ai essayé de supprimer la réplication et de la recréer (nous avons un script pour la recréer à partir de zéro). Je ne sais pas exactement ce que j'ai fait, mais maintenant il est dans un état complètement foiré et je ne peux pas le réparer.

Tout d'abord, j'essaye de me débarrasser de l'abonnement (sur le serveur éditeur):

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

Cela semble fonctionner. SELECT * FROM syssubscriptionsne montre aucun résultat. En regardant sur le serveur d'abonné, SSMS> {SubscriberServer}> Réplication> Abonnements locaux - l'abonnement n'est pas là.

Alors j'essaie de supprimer la publication. SSMS> {Server}> Réplication> Publications locales> {PublicationName}> Supprimer. Cela donne le message d'erreur suivant:

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, donc j'essaye de laisser tomber les articles:

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

et obtenez cette erreur:

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, donc j'essaye de démarrer l'agent Snapshot et j'obtiens cette exception SQL interne:

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

J'ai donc essayé une autre méthode de suppression de l'article, DELETE FROM sysarticles. Cela semble avoir fonctionné - je me suis maintenant débarrassé des articles, mais j'obtiens toujours la même erreur «Impossible de supprimer la publication car il existe au moins un abonnement pour cette publication» lorsque j'essaie de supprimer la publication.

J'ai également redémarré SQL Server - n'a pas aidé.

Je ne sais pas ce qui se passe ici et comment y remédier?

BTW c'est ce qui se passe lorsque vous donnez à un développeur de logiciels qui en sait juste assez pour être dangereux les clés de la base de données. Heureusement, ce n'est pas un environnement de production ...

Grand gars
la source

Réponses:

10

TLDR:

Il semble que la désactivation et la réactivation de la réplication aient probablement résolu le problème:

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

Je suppose que c'est l'équivalent de l'éteindre puis de le rallumer ...

Version plus longue:

Un collègue a essayé de le réparer. Il a essayé quelques choses mais n'est pas allé très loin. Le seul changement qu'il a fait avant d'abandonner a été de désactiver la réplication.

J'ai ensuite essayé la suggestion de Cody . La commande sp_dropsubscription s'est plainte qu'aucun abonnement n'existe. J'ai donc essayé la commande sp_droppublication. Cela s'est plaint que la réplication n'était pas activée sur la base de données. Je l'ai donc activé et relancé la commande. Cette fois, il s'est plaint que la publication n'existait pas. J'ai actualisé le nœud des publications locales dans SSMS et bien sûr qu'il avait disparu. J'ai exécuté le script de configuration de la réplication, généré un nouvel instantané et tout fonctionne maintenant correctement. Joie!

Je ne suis pas sûr à 100% que la désactivation et l'activation de la réplication soient ce qui a réellement résolu le problème, mais cela vaut vraiment la peine d'essayer si la réplication est gâchée.

Grand gars
la source
Bonne lecture pour les débutants. Est-il sûr de dire que vous devez d'abord désactiver la réplication avant de restaurer la base de données?
Keith Rivera du
Je vais certainement essayer cela la prochaine fois - d'après ce que j'ai lu, la réplication ne devrait pas être complètement époustouflée et recréée (comme je le pensais initialement). Désactivez la réplication, restaurez la base de données, activez la réplication, envoyez un nouvel instantané. Tant que les articles sont toujours valables, il devrait être bon d'y aller.
Ça
Débutant en réplication totale ici, mais suivant le TLDR; instructions a conduit à la disparition de mes publications de SSMS. L'interrogation MSPublicationsdans la distributionbase de données révèle que la publication a bel et bien disparu. Est-ce attendu?
pimbrouwers
5

J'ai eu un problème avec la réplication et l'ai résolu avec ce

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

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

Cela et:

exec sp_cleanupdbreplication

Sont les sauveurs lors du nettoyage des réplications en désordre.

Guillermo Zooby
la source
1
Je crois que votre message vient de m'éviter de réinitialiser mon environnement de test. Je ne sais pas quelle commande ci-dessus l'a fait, mais je peux maintenant supprimer les index sans l'erreur sur leur publication pour la réplication. Merci beaucoup à vous.
MHSQLDBA
2

La restauration de la base de données interrompt la réplication, c'est donc normal. De plus, la plupart des autres messages d'erreur ne sont que des suivis car vous n'avez pas pu supprimer tous les abonnements (ou du moins SQL le pense).

Vous savez que vous avez votre éditeur (la base de données source), et au moins un abonné (la base de données de destination), et qu'il s'agit de deux serveurs différents. Je veux juste mentionner qu'il y a aussi un distributeur qui se trouve sur l'un ou l'autre de ces serveurs, et probablement dans une base de données nommée distribution. Parfois, il contient des informations utiles et parfois les choses tombent parce que les informations entre les trois ne correspondent pas.

Quoi qu'il en soit, lorsque vous avez vérifié les abonnés, avez-vous également vérifié cette section sur le serveur de l' éditeur pour vous assurer qu'il n'y avait rien d'autre dans la liste? Si vous en trouvez, vous pouvez essayer de le supprimer manuellement:

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

Mais en supposant qu'ils ont vraiment disparu, essayez ceci sur la base de données de l'éditeur:

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

Tiens nous au courant de comment ça se passe. La réplication quand elle entre dans cet état me confond, moi et les autres bons DBA, rien à voir avec le fait d'être développeur :-)

Cody Konior
la source
Merci pour la suggestion. La commande sp_dropsubscription s'est plainte qu'aucun abonnement n'existe. La commande sp_droppublication s'est plainte que la réplication n'était pas activée - ce qui m'a conduit à ce qui semble être la solution.
TallGuy
Pour moi, la commande sp_removedbreplication fonctionnait la plupart du temps chaque fois que je devais supprimer de force la réplication.
SQLPRODDBA
0

La seule façon dont j'ai pu me débarrasser des artefacts de réplication fantôme est de supprimer les abonnements, les articles et les publications. S'il existe toujours des abonnements fantômes, recréez la publication, y compris l'abonné fantôme. Cela semble fonctionner avec les anciennes versions en particulier.

Edwina Montague-Martin
la source
0

c'est ce que je fais normalement quand j'ai une publication qui est foirée.

c'est un peu moche mais ça a fonctionné pour moi à plusieurs reprises sur des environnements différents. quelles sont les causes? qui est parfois difficile de le comprendre, le mieux est parfois repartir de zéro, mais même pour que vous devez éclaircir allla residualsde la publication actuelle qui est défectueuse.

juste pour le mettre en contexte:

Voici ce que je vois du moniteur de réplication:

entrez la description de l'image ici

et lorsque j'utilise mon propre moniteur de réplication à l'aide de 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 

vous pouvez voir 2 lignes sur la dernière case ci-dessous - et l'une d'entre elles ne devrait pas être là:

entrez la description de l'image ici

la même chose quand j'utilise ce script:

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

entrez la description de l'image ici

D'abord, vous faites ce qui est indiqué dans les autres réponses ci-dessus, si cela fonctionne , c'est bien, cela fonctionne parfois, problème résolu.

ce serait plus ou moins ça:

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

Maintenant, pour nous débarrasser complètement de cette publication, nous allons commencer par nous connecter au buscriber, puis à l'éditeur, puis au distributeur selon le script ci-dessous:

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

à ce stade, recréez la publication comme vous le feriez normalement

puis mettez l'instantané à exécuter

attendez qu'il ait fini de générer l'instantané

MAYBE YOU DONT NEED TO RUN THE SNAP- essayez de l' withoutexécuter en premier, la plupart du temps cela fonctionne, vous pouvez également ajouter seulement 1-2 smallarticles à la publication afin que le snap s'exécute rapidement

mais si vous exécutez l'instantané, vous devez attendre qu'il se termine avant de passer à l'étape suivante - drop the publication

entrez la description de l'image ici

après cela, vous générez les scripts drop that publicationselon l'image ci-dessous: entrez la description de l'image ici

après cela, espérons-le, lorsque vous exécutez nos scripts originaux ci - dessus , ou regardez le moniteur de réplication, vous ne verrez pas la publication défectueuse, seulement les bonnes, dans mon cas juste une:

entrez la description de l'image ici

Marcello Miorelli
la source
-1

J'ai eu le même problème sur ma box de pré-production, la commande

exec sp_cleanupdbreplication

semblent avoir travaillé sur le nettoyage de fausses entrées d'abonnement ...

CARLA
la source