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)

OK、それで私は記事を落とそうとします:

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。これは機能したようです-記事を削除しましたが、パブリケーションを削除しようとすると、「このパブリケーションには少なくとも1つのサブスクリプションが存在するため、パブリケーションをドロップできません」というエラーが発生します。

SQL Serverも再起動しましたが、役に立ちませんでした。

ここで何が起こっているのかわからないのですが、どうすれば修正できますか?

ところで、これは危険なほど十分に知っているソフトウェア開発者にデータベースのキーを与えるとどうなるかです。幸い、これは本番環境ではありません...

回答:


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'

これは、スイッチをオフにしてから再びオンにするのと同じです...

長いバージョン:

同僚はそれを修正しようと試みました。彼はいくつかのことを試しましたが、それほど遠くに行きませんでした。彼が諦める前に行った変更の1つは、レプリケーションを無効にすることでした。

次に、コーディの提案を試しました。sp_dropsubscriptionコマンドは、サブスクリプションが存在しないと報告しました。そこで、sp_droppublicationコマンドを試してみました。これにより、データベースでレプリケーションが有効になっていなかったという不満がありました。だから私はそれを有効にしてコマンドを再実行しました。今回はその出版物が存在しないと不満を述べた。SSMSで[ローカルパブリケーション]ノードを更新しましたが、十分に削除されました。レプリケーション設定スクリプトを実行し、新しいスナップショットを生成しましたが、すべてが正常に機能しています。喜び!

レプリケーションの無効化と有効化が実際に問題を解決したかどうかは100%確実ではありませんが、レプリケーションがめちゃくちゃになった場合は、試す価値があります。


初心者のための素晴らしい読書。データベースを復元する前に、まずレプリケーションを無効にする必要があると言っても安全ですか?
キース・リベラ

私は確かに次の機会にそれを試すつもりです-私が読んだものから、複製を完全に吹き飛ばして再作成する必要はありません(最初にそう思ったように)。レプリケーションを無効にし、データベースを復元し、レプリケーションを有効にし、新しいスナップショットをプッシュします。記事がまだ有効である限り、それは行くべきです。とにかく試してみる価値があります...
TallGuy

トータルレプリケーションの初心者ですが、TLDRに従っています。指示により、SSMSから私の出版物が消えました。データベースでクエリMSPublicationsdistribution実行すると、パブリケーションが実際になくなっていることがわかります。これは予想されますか?
pimbrouwers 2017年

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 2018

2

データベースを復元するとレプリケーションが中断するため、これは正常です。また、他のほとんどのエラーメッセージは、すべてのサブスクリプションを削除できなかった(または少なくともSQLがそう思っている)ため、その後に続くものです。

パブリッシャー(ソースデータベース)と少なくとも1つのサブスクライバー(宛先データベース)があり、これらは2つの異なるサーバーであることを知っています。これらのサーバーまたは別のサーバーのいずれかにあり、おそらくdistributionという名前のデータベースにあるディストリビューターもあることを述べておきたいと思います。中には有用な情報が含まれていることもあれば、3つの情報が一致していないために状況が崩れることもあります。

とにかく、サブスクライバーをチェックしたときに、パブリッシャーサーバーのそのセクションもチェックして、他に何もリストされていないことを確認しましたか?見つかった場合は、手動で削除してみてください。

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 2016

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行ありますが、1行はそこに表示されません。

ここに画像の説明を入力してください

このスクリプトを使用する場合も同じです。

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

偽のサブスクリプションエントリのクリーンアップに取り組んだようです...

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.