如何在MS SQL Server上修复混乱的复制


11

我从备份还原了数据库。数据库使用复制发布到其他服务器。假设数据库还原会破坏复制,我尝试删除该复制并重新创建它(我们有一个脚本可以从头开始重新创建它)。我不确定自己所做的确切,但是现在它处于完全混乱的状态,我无法修复。

首先,我尝试摆脱订阅(在发布服务器上):

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

这似乎有效。SELECT * FROM syssubscriptions没有显示结果。在订阅服务器上,SSMS> {SubscriberServer}>复制>本地订阅-订阅不存在。

因此,我尝试删除该出版物。SSMS> {服务器}>复制>本地发布> {PublicationName}>删除。这给出以下错误信息:

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

好的,所以我尝试删除文章:

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

并得到这个错误:

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.

好的,所以我尝试启动快照代理,并得到以下内部SQL异常:

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

因此,我尝试了一种删除文章的替代方法DELETE FROM sysarticles。这似乎奏效了-我现在摆脱了这些文章,但是当我尝试删除该出版物时,仍然收到相同的“无法删除该出版物,因为该出版物至少存在一个订阅”错误。

我还重新启动了SQL Server-没有帮助。

我不知道这是怎么回事,如何解决?

顺便说一句,当您给一个足够了解数据库密钥危险的软件开发人员时,就会发生这种情况。幸运的是,这不是生产环境...

Answers:


10

TLDR:

似乎禁用并重新启用复制可能解决了此问题:

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

我想这相当于先将其关闭然后再重新打开...

较长版本:

一个同事可以尝试修复它。他尝试了一些尝试,但并没有走得太远。他放弃之前所做的一项更改是禁用复制。

然后,我尝试了科迪的建议。sp_dropsubscription命令抱怨没有订阅存在。所以我尝试了sp_droppublication命令。这抱怨数据库未启用复制。所以我启用了它并重新运行了命令。这次,它抱怨该出版物不存在。我刷新了SSMS中的“本地出版物”节点,并确定它已经消失了。我运行了复制设置脚本,生成了一个新的快照,现在一切正常。喜悦!

我不能100%地确定禁用和启用复制实际上可以解决问题,但是如果复制搞砸了,绝对值得尝试。


非常适合新手阅读。可以肯定地说,在还原数据库之前应先禁用复制吗?
基思·里维拉

我当然会下一次尝试-从我所读的内容中,不必完全删除并重新创建复制(就像我最初认为的那样)。禁用复制,还原数据库,启用复制,推送新快照。只要文章仍然有效,就应该很好。无论如何值得一试...
TallGuy 2016年

总复制新手,但遵循TLDR;指示导致我的出版物从SSMS消失了。MSPublicationsdistribution数据库中查询表明该出版物确实消失了。这是预期的吗?
pimbrouwers 17-10-16

5

我对复制一团糟,并以此解决了

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

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

那和:

exec sp_cleanupdbreplication

是清理混乱的复制时的救星。


1
我相信您的帖子只是让我免于重新设置测试环境。不知道上面是哪个命令执行的,但是我现在可以删除索引,而不会出现有关它们被发布以进行复制的错误。非常感谢你。
MHSQLDBA

2

还原数据库将破坏复制,因此很正常。另外,大多数其他错误消息也只是在后面,因为您无法删除所有订阅(或者至少SQL如此认为)。

您知道您拥有发布者(源数据库)和至少一个订阅者(目标数据库),并且它们是两台不同的服务器。我只想提到,在这些服务器或另一台服务器上还有一个分发服务器,并且可能在名为分发服务器的数据库中。有时它那里有一些有用的信息,有时又会掉下来,因为这三个之间的信息不一致。

无论如何,当您检查订阅者时,是否还要检查发布者服务器上的该部分以确保没有列出其他内容?如果找到任何内容,可以尝试手动将其删除:

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

但是,假设它们真的消失了,请在发布者数据库上尝试以下操作:

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

让我们知道怎么回事。进入这种状态时进行复制会使我和其他优秀的DBA感到困惑,与成为开发人员完全无关:-)


谢谢你的建议。sp_dropsubscription命令抱怨没有订阅存在。sp_droppublication命令抱怨未启用复制-这导致我找到了解决方案。
TallGuy 2016年

对于我来说,每当我不得不强制删除复制时,sp_removedbreplication命令在大多数情况下都有效。
SQLPRODDBA '16

0

我摆脱幻影复制工件的唯一方法是删除订阅,文章和出版物。如果仍然有幻像订阅,则重新创建包含幻像订阅者的发布。这似乎尤其适用于旧版本。


0

当出版物被弄乱时,这通常是我要做的。

这有点丑陋,但是它在不同环境下多次为我工作。是什么原因造成的?这是有时很难搞清楚,最好有时从头开始,但即使你需要清理allresiduals从当前出版物是错误的。

只是将它放在上下文中:

这是我从复制监视器看到的内容:

在此处输入图片说明

当我通过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 

您会在下面的最后一个方框中看到2行-而其中不应有一行:

在此处输入图片说明

使用此脚本时相同:

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

在此处输入图片说明

首先,您要执行上面其他答案中显示的操作,如果该方法有效,那很好,有时它可以解决问题。

那就更少了:

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

现在,要完全摆脱此出版物,我们将首先连接到总线管理员,然后是发布者,然后是分发者,方法如下:

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

此时,您将像通常那样重新创建发布

然后将快照运行

等待它完成快照生成

MAYBE YOU DONT NEED TO RUN THE SNAP-尝试without在大多数情况下先运行它,也可以small在出版物中只添加1-2 篇文章,以便快速运行快照

但是,如果您运行快照,则需要等到快照完成后才能进行下一步- drop the publication

在此处输入图片说明

之后,您将生成脚本,drop that publication如下图所示: 在此处输入图片说明

在那之后希望,当您运行上面的原始脚本或查看复制监视器时,您将不会看到错误的发布,只有好的发布,在我的情况下只有一个:

在此处输入图片说明


-1

我在预生产包装盒上遇到了相同的问题,命令

exec sp_cleanupdbreplication

似乎已经在清理虚假的订阅条目...

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.