Як виправити заплутану реплікацію на 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.