Jak naprawić pomieszaną replikację na MS SQL Server

11

Przywróciłem bazę danych z kopii zapasowej. Baza danych używa replikacji do publikowania na innym serwerze. Zakładając, że przywrócenie bazy danych zepsułoby replikację, próbowałem usunąć replikę i ponownie ją utworzyć (mamy skrypt do jej ponownego utworzenia od zera). Nie jestem pewien, co dokładnie zrobiłem, ale teraz jest w kompletnie popsutym stanie i nie mogę tego naprawić.

Najpierw staram się pozbyć subskrypcji (na serwerze wydawcy):

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

To wydaje się działać. SELECT * FROM syssubscriptionsnie pokazuje wyników. Patrząc na serwerze subskrybenta, SSMS> {SubscriberServer}> Replikacja> Subskrypcje lokalne - subskrypcji tam nie ma.

Więc próbuję usunąć publikację. SSMS> {Serwer}> Replikacja> Lokalne publikacje> {PublicationName}> Usuń. Daje to następujący komunikat o błędzie:

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, więc próbuję upuścić artykuły:

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

i otrzymaj ten błąd:

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.

Ok, więc próbuję uruchomić Agenta migawki i otrzymuję ten wewnętrzny wyjątek SQL:

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

Spróbowałem więc alternatywną metodę usuwania artykułu DELETE FROM sysarticles. Wygląda na to, że zadziałało - teraz pozbyłem się artykułów, ale wciąż pojawia się ten sam błąd „Nie można upuścić publikacji, ponieważ istnieje co najmniej jedna subskrypcja dla tej publikacji”, gdy próbuję usunąć publikację.

Ponownie uruchomiłem SQL Server - nie pomogłem.

Nie wiem, co się tutaj dzieje i jak to naprawić?

BTW, tak się dzieje, gdy dajesz programistom, którzy wiedzą wystarczająco dużo, aby być niebezpiecznym, klucze do bazy danych. Na szczęście nie jest to środowisko produkcyjne ...

Wysoki facet
źródło

Odpowiedzi:

10

TLDR:

Wygląda na to, że wyłączenie i ponowne włączenie replikacji prawdopodobnie rozwiązało problem:

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

Wydaje mi się, że jest to odpowiednik wyłączenia i ponownego włączenia ...

Dłuższa wersja:

Kolega z pracy próbował to naprawić. Próbował kilku rzeczy, ale nie zaszedł zbyt daleko. Jedyną zmianą, którą dokonał przed poddaniem się, było wyłączenie replikacji.

Potem wypróbowałem sugestię Cody'ego . Komenda sp_dropsubscription narzekała, że ​​nie istnieją żadne subskrypcje. Więc spróbowałem polecenia sp_droppublication. Narzekało to, że replikacja nie została włączona w bazie danych. Więc włączyłem go i ponownie uruchomiłem polecenie. Tym razem narzekała, że ​​publikacja nie istnieje. Odświeżyłem węzeł Local Publications w SSMS i na pewno już go nie ma. Uruchomiłem skrypt konfiguracji replikacji, wygenerowałem nową migawkę i wszystko działa teraz poprawnie. Radość!

Nie jestem w 100% pewien, że wyłączenie i włączenie replikacji faktycznie naprawiło problem, ale zdecydowanie warto spróbować, jeśli replikacja się nie powiedzie.

Wysoki facet
źródło
Świetna lektura dla początkujących. Czy można bezpiecznie powiedzieć, że należy najpierw wyłączyć replikację przed przywróceniem bazy danych?
Keith Rivera,
Z pewnością spróbuję to następnym razem - z tego, co przeczytałem, replika nie powinna być całkowicie zdmuchnięta i odtworzona (jak początkowo myślałem, że tak będzie). Wyłącz replikację, przywróć bazę danych, włącz replikację, wypchnij nową migawkę. Tak długo, jak artykuły są nadal aktualne, powinno być dobrze. W każdym razie warto spróbować ...
TallGuy,
Całkowita replikacja dla początkujących tutaj, ale zgodnie z TLDR; instrukcje doprowadziły do ​​zniknięcia moich publikacji z SSMS. Zapytania MSPublicationsw distributionbazie danych ujawniają, że publikacja rzeczywiście zniknęła. Czy jest to oczekiwane?
pimbrouwers
5

Miałem bałagan z replikacją i rozwiązałem to dzięki temu

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

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

To i:

exec sp_cleanupdbreplication

Są wybawcami podczas sprzątania pomieszanych replik.

Guillermo Zooby
źródło
1
Wydaje mi się, że Twój post uratował mnie przed ponownym skonfigurowaniem środowiska testowego. Nie jestem pewien, które z powyższych poleceń to zrobiło, ale mogę teraz usunąć indeksy bez błędu publikowania ich w celu replikacji. Wielkie dzięki.
MHSQLDBA
2

Przywrócenie bazy danych spowoduje przerwanie replikacji, więc jest to normalne. Również większość innych komunikatów o błędach jest następstwem, ponieważ nie udało się usunąć wszystkich subskrypcji (a przynajmniej SQL tak uważa).

Wiesz, że masz swojego wydawcę (źródłową bazę danych) i co najmniej jednego subskrybenta (docelową bazę danych) i że są to dwa różne serwery. Chcę tylko wspomnieć, że jest też dystrybutor, który jest na jednym z tych serwerów lub innym, i prawdopodobnie w bazie danych o nazwie dystrybucja. Czasami zawiera przydatne informacje, a czasem rzeczy się przewracają, ponieważ informacje między tymi trzema są niezgodne.

W każdym razie, kiedy sprawdziłeś subskrybentów, czy sprawdziłeś również tę sekcję na serwerze wydawcy , aby upewnić się, że nic więcej nie ma na liście? Jeśli znajdziesz, możesz spróbować usunąć go ręcznie:

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

Ale zakładając, że naprawdę ich nie ma, wypróbuj to w bazie danych wydawcy:

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

Poinformuj nas jak to idzie. Replikacja, gdy przejdzie w ten stan, wprawia mnie w zakłopotanie, a inne dobre DBA nie mają nic wspólnego z byciem programistą :-)

Cody Konior
źródło
Dzieki za sugestie. Komenda sp_dropsubscription narzekała, że ​​nie istnieją żadne subskrypcje. Komenda sp_droppublication narzekała, że ​​replikacja nie została włączona - co doprowadziło mnie do rozwiązania, które wydaje się być rozwiązaniem.
TallGuy 19.04.16
Dla mnie polecenie sp_removedbreplication działało przez większość czasu, gdy musiałem wymusić usunięcie replikacji.
SQLPRODDBA
0

Jedynym sposobem, w jaki udało mi się pozbyć fantomowych replikacji replik, jest porzucenie subskrypcji, artykułów, publikacji. Jeśli nadal istnieją subskrypcje fantomowe, ponownie utwórz publikację, w tym subskrybenta fantomowego. Wydaje się, że działa to szczególnie ze starszymi wersjami.

Edwina Montague-Martin
źródło
0

to zwykle robię, gdy mam pomieszaną publikację.

jest to trochę brzydkie, ale wielokrotnie działało dla mnie w różnych środowiskach. co to powoduje? że czasem trudno jest zrozumieć to, czasami najlepiej jest zacząć od zera, ale nawet, że trzeba wyjaśnić z bieżącego wydania że jest uszkodzony.allresiduals

aby umieścić to w kontekście:

Oto, co widzę z monitora replikacji:

wprowadź opis zdjęcia tutaj

a kiedy używam własnego monitora replikacji za pomocą 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 

w ostatnim polu poniżej widać 2 linie - i jednej nie powinno się tam znajdować:

wprowadź opis zdjęcia tutaj

to samo, gdy używam tego skryptu:

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

wprowadź opis zdjęcia tutaj

Najpierw zrób to, co pokazano w innych odpowiedziach powyżej, jeśli to działa , to dobrze, czasem działa, problem rozwiązany.

byłoby mniej więcej:

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

Teraz, aby całkowicie pozbyć się tej publikacji, zaczniemy od połączenia z Buscriberem, a następnie z wydawcą, a następnie dystrybutorem zgodnie z poniższym skryptem:

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

w tym momencie ponownie utwórz publikację, jak zwykle

następnie uruchom migawkę

poczekaj, aż zakończy generowanie migawki

MAYBE YOU DONT NEED TO RUN THE SNAP- spróbuj withouturuchomić go najpierw, przez większość czasu działa, możesz również dodać tylko 1-2 smallartykuły do ​​publikacji, dzięki czemu przystawka działa szybko

ale jeśli uruchomisz migawkę, musisz poczekać, aż zakończy się, zanim przejdziesz do następnego kroku - drop the publication

wprowadź opis zdjęcia tutaj

po tym generujesz skrypty drop that publicationzgodnie z poniższym obrazkiem: wprowadź opis zdjęcia tutaj

po tym, mam nadzieję, że kiedy uruchomisz nasze oryginalne skrypty powyżej lub spojrzysz na monitor replikacji, nie zobaczysz wadliwej publikacji, tylko dobre, w moim przypadku tylko jedną:

wprowadź opis zdjęcia tutaj

Marcello Miorelli
źródło
-1

Polecenie dotyczyło tego samego problemu na moim pudełku przedprodukcyjnym

exec sp_cleanupdbreplication

Wygląda na to, że pracował nad usunięciem fałszywych wpisów subskrypcji ...

CARLA
źródło