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.

좋습니다. Snapshot Agent를 시작하려고하면이 내부 SQL 예외가 발생합니다.

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

그래서 기사를 삭제하는 다른 방법을 시도했습니다 DELETE FROM sysarticles. 이것은 효과가있는 것으로 보입니다. 이제 기사를 제거했지만 발행물을 삭제하려고 할 때 여전히 '이 발행물에 대해 하나 이상의 구독이 존재하므로 발행물을 삭제할 수 없습니다'라는 오류가 발생합니다.

또한 SQL Server를 다시 시작했지만 도움이되지 않았습니다.

여기서 무슨 일이 일어나고 있는지 어떻게 알 수 있습니까?

BTW 이것은 데이터베이스의 키를 위험에 빠뜨릴만큼 충분히 알고있는 소프트웨어 개발자에게 제공 할 때 발생합니다. 다행히도 이것은 프로덕션 환경이 아닙니다 ...

답변:


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'

나는 이것이 스위치를 껐다가 다시 켜는 것과 같습니다.

더 긴 버전 :

직장 동료가 고치려고 노력했습니다. 그는 몇 가지를 시도했지만 멀리 가지 못했습니다. 그가 포기하기 전에 한 가지 변경은 복제를 비활성화하는 것이 었습니다.

그런 다음 Cody의 제안 을 시도했습니다 . sp_dropsubscription 명령이 구독이 존재하지 않는다고 불평했습니다. 그래서 sp_droppublication 명령을 시도했습니다. 데이터베이스에서 복제가 활성화되지 않았다고 불평했습니다. 그래서 그것을 활성화하고 명령을 다시 실행했습니다. 이번에는 출판물이 존재하지 않는다고 불평했다. SSMS에서 Local Publications (로컬 게시) 노드를 새로 고쳤으며 제대로 끝났는지 확인합니다. 복제 설정 스크립트를 실행하고 새 스냅 샷을 생성했으며 모든 것이 이제 제대로 작동합니다. 즐거움!

복제를 비활성화하고 활성화하는 것이 실제로 문제를 해결 한 것이라고 100 % 확신 할 수는 없지만 복제가 엉망이되면 시도해 볼 가치가 있습니다.


초보자를위한 대단한 독서. 데이터베이스를 복원하기 전에 먼저 복제를 비활성화해야한다고 말하는 것이 안전합니까?
Keith Rivera

나는 다음 번에 그것을 시도 할 것입니다-내가 읽은 것에서 복제가 완전히 날아 갔거나 다시 만들어 질 필요는 없습니다 (처음 생각했던 것처럼). 복제 비활성화, 데이터베이스 복원, 복제 활성화, 새 스냅 샷 푸시 기사가 여전히 유효한 한 계속 진행해야합니다. 어쨌든 시도 가치가 ...
TallGuy

여기에서 TLDR을 따르는 전체 복제 초보자; 지침으로 인해 SSMS에서 내 간행물이 사라졌습니다. 데이터베이스 MSPublications에서 쿼리 distribution하면 게시가 실제로 사라 졌음을 알 수 있습니다. 이것이 예상됩니까?
pimbrouwers

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

나에게 sp_removedbreplication 명령은 복제를 강제로 제거해야 할 때마다 대부분 작동했습니다.
SQLPRODDBA

0

팬텀 복제 아티팩트를 제거 할 수있는 유일한 방법은 구독, 기사, 발행물을 삭제하는 것입니다. 여전히 팬텀 구독이있는 경우 팬텀 구독자를 포함하여 발행물을 다시 작성하십시오. 이것은 특히 이전 버전에서 작동하는 것 같습니다.


0

이것은 내가 엉망인 출판물을 가질 때 일반적으로하는 일입니다.

그것은 조금 추악하지만 다른 환경에서 여러 번 나를 위해 일했습니다. 무엇이 원인입니까? 때로는 이해하기 어려우며, 처음부터 시작하는 것이 가장 좋지만, 심지어 현재 출판물에서 결함이있는 부분 을 정리해야 all합니다 residuals.

컨텍스트에 넣으려면 :

이것이 복제 모니터에서 보는 것입니다.

여기에 이미지 설명을 입력하십시오

그리고 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 

아래 마지막 상자에 두 줄이 표시됩니다. 한 줄은 없어야합니다.

여기에 이미지 설명을 입력하십시오

이 스크립트를 사용할 때도 마찬가지입니다.

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

이제이 발행물을 완전히 없애기 위해 아래 스크립트에 따라 buscriber, 게시자 및 배포자에 연결하여 시작합니다.

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

가짜 구독 항목을 정리하는 데 도움이 된 것 같습니다 ...

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.