Як виправити заплутану реплікацію на 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 і отримаю цей внутрішній виняток SQL:

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

Так що я спробував альтернативний метод видалення статті DELETE FROM sysarticles. Здається, це спрацювало - я тепер позбувся статей, але все одно отримую ту саму помилку "Не можу відмовитись від публікації, тому що принаймні одна підписка існує на цю публікацію", коли я намагаюся видалити публікацію.

Я також перезапустив 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'

Я думаю, це еквівалент вимкнення, а потім знову включення ...

Більш дрібна версія:

Робітниця намагалася виправити це. Він спробував кілька речей, але не зайшов дуже далеко. Єдиною зміною, яку він вніс перед відмовою, було відключення реплікації.

Потім я спробував пропозицію Коді . Команда sp_dropsubscriptions поскаржилася, що підписок немає. Тому я спробував команду sp_droppublication. Він скаржився, що реплікація не була включена в базі даних. Тому я ввімкнув це і повторно запустив команду. Цього разу він скаржився, що видання не існує. Я оновив вузол локальних публікацій у SSMS і досить впевнений, що він пішов. Я запустив сценарій налаштування реплікації, створив новий знімок і тепер все працює належним чином. Радість!

Я не на 100% впевнений, що вимкнення та включення реплікації - це те, що насправді вирішило проблему, але, безумовно, варто спробувати, якщо реплікація зіпсується.


Прекрасне читання для новачків. Чи безпечно сказати, що спочатку слід відключити реплікацію, перш ніж відновити базу даних?
Кіт Рівера

Я, безумовно, спробую це наступного разу - з того, що я прочитав, тиражування не повинно бути повністю здутим і відтвореним (як я спочатку думав, що це буде). Вимкніть реплікацію, відновіть базу даних, увімкніть реплікацію, надішліть новий знімок. Поки статті все ще діють, слід добре пройти. Варто все-таки спробувати ...
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_dropsubscriptions поскаржилася, що підписок немає. Команда 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

Тепер, щоб повністю позбутися цієї публікації, ми розпочнемо з підключення до програми, що видає, а потім видавця, а потім дистриб'ютора, як зазначено нижче в сценарії:

-- 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запустити його спочатку, більшість часу це працює, також ви можете додати лише 1-2 smallстатті до публікації, так що оснастка швидко працює

але якщо ви запускаєте знімок, тоді вам потрібно почекати, поки він закінчиться, перш ніж перейти до наступного кроку - drop the publication

введіть тут опис зображення

після цього ви генеруєте сценарії drop that publicationвідповідно до малюнка нижче: введіть тут опис зображення

після цього, сподіваємось, що коли ви запустите наші оригінальні сценарії вище або подивитесь на монітор реплікації, ви не побачите несправних публікацій, лише хороших, у моєму випадку лише одного:

введіть тут опис зображення


-1

У мене була така ж проблема в моєму передвиробничому вікні, команді

exec sp_cleanupdbreplication

схоже, працювали над очищенням фіктивних записів підписки ...

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.