Cara memperbaiki replikasi kacau pada MS SQL Server

11

Saya memulihkan database dari cadangan. Basis data menggunakan replikasi untuk menerbitkan ke server yang berbeda. Dengan asumsi pemulihan basis data akan merusak replikasi, saya mencoba menghapus replikasi dan membuatnya kembali (kami memiliki skrip untuk membuatnya kembali dari awal). Saya tidak yakin persis apa yang saya lakukan, tetapi sekarang dalam keadaan benar-benar kacau dan saya tidak bisa memperbaikinya.

Pertama, saya mencoba untuk menyingkirkan langganan (di server penerbit):

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

Ini sepertinya berhasil. SELECT * FROM syssubscriptionstidak menunjukkan hasil. Melihat pada server pelanggan, SSMS> {SubscriberServer}> Replikasi> Langganan Lokal - langganannya tidak ada.

Maka saya mencoba untuk menghapus publikasi. SSMS> {Server}> Replikasi> Publikasi Lokal> {PublicationName}> Hapus. Ini memberikan pesan kesalahan berikut:

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, jadi saya mencoba untuk menjatuhkan artikel:

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

dan dapatkan kesalahan ini:

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.

Oke, jadi saya mencoba memulai Snapshot Agent dan saya mendapatkan pengecualian SQL internal ini:

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

Jadi saya mencoba metode alternatif untuk menghapus artikel DELETE FROM sysarticles,. Tampaknya ini berhasil - saya sekarang sudah menyingkirkan artikel, tetapi saya masih mendapatkan kesalahan yang sama 'Tidak dapat melepaskan publikasi karena setidaknya ada satu langganan untuk publikasi ini' ketika saya mencoba menghapus publikasi.

Saya juga me-restart SQL Server - tidak membantu.

Saya tidak tahu apa yang sedang terjadi di sini dan bagaimana cara memperbaikinya?

BTW inilah yang terjadi ketika Anda memberi pengembang perangkat lunak yang tahu hanya cukup berbahaya kunci ke database. Untungnya, ini bukan lingkungan produksi ...

TallGuy
sumber

Jawaban:

10

TLDR:

Tampaknya menonaktifkan dan mengaktifkan kembali replikasi mungkin memperbaiki masalah:

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

Saya kira ini setara dengan mematikannya dan kemudian kembali lagi ...

Versi yang lebih panjang:

Seorang teman kerja mencoba memperbaikinya. Dia mencoba beberapa hal tetapi tidak terlalu jauh. Satu perubahan yang dia lakukan sebelum menyerah adalah menonaktifkan replikasi.

Saya kemudian mencoba saran Cody . Perintah sp_dropsubscription mengeluh bahwa tidak ada langganan. Jadi saya mencoba perintah sp_droppublication. Ini mengeluh bahwa replikasi tidak diaktifkan pada database. Jadi saya mengaktifkannya dan menjalankan kembali perintah. Kali ini mengeluh bahwa publikasi itu tidak ada. Saya menyegarkan simpul Publikasi Lokal di SSMS dan cukup yakin sudah hilang. Saya menjalankan skrip pengaturan replikasi, menghasilkan snapshot baru dan semuanya sekarang berfungsi dengan baik. Kegembiraan!

Saya tidak 100% yakin bahwa menonaktifkan dan mengaktifkan replikasi adalah apa yang sebenarnya memperbaiki masalah, tetapi pasti patut dicoba jika replikasi itu kacau.

TallGuy
sumber
Bacaan yang bagus untuk pemula. Apakah aman untuk mengatakan bahwa Anda harus menonaktifkan replikasi terlebih dahulu sebelum mengembalikan database?
Keith Rivera
Saya pasti akan mencobanya lain kali - dari apa yang saya baca, replikasi tidak harus benar-benar terpesona dan diciptakan kembali (seperti yang saya pikir pada awalnya). Nonaktifkan replikasi, pulihkan database, aktifkan replikasi, dorong snapshot baru. Selama artikel itu masih berlaku, itu harus baik untuk pergi. Pantas untuk dicoba ...
TallGuy
Replikasi total pemula di sini, tetapi mengikuti TLDR; instruksi telah menyebabkan hilangnya publikasi saya dari SSMS. Permintaan MSPublicationsdalam distributiondatabase mengungkapkan bahwa publikasi memang hilang. Apakah ini yang diharapkan?
pimbrouwers
5

Saya memiliki masalah dengan replikasi dan menyelesaikannya dengan ini

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

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

Itu dan:

exec sp_cleanupdbreplication

Apakah penyelamat saat membersihkan replikasi kacau.

Guillermo Zooby
sumber
1
Saya yakin Posting Anda baru saja menyelamatkan saya dari pengaturan ulang lingkungan Pengujian saya. Tidak yakin perintah mana di atas yang melakukannya, tetapi saya sekarang dapat menghapus indeks tanpa kesalahan tentang mereka yang diterbitkan untuk replikasi. Terima kasih banyak.
MHSQLDBA
2

Mengembalikan database akan merusak replikasi, jadi itu normal. Juga sebagian besar pesan kesalahan lainnya hanya mengikuti karena Anda belum dapat menghapus semua langganan (atau setidaknya SQL berpikir demikian).

Anda tahu Anda memiliki penerbit (sumber basis data), dan setidaknya satu pelanggan (basis data tujuan), dan ini adalah dua server yang berbeda. Saya hanya ingin menyebutkan bahwa ada juga distributor yang ada di salah satu dari server ini atau yang lain, dan kemungkinan dalam database bernama distribusi. Terkadang ada beberapa info berguna di sana dan kadang-kadang hal-hal jatuh karena informasi antara ketiganya tidak cocok.

Lagi pula, ketika Anda memeriksa pelanggan, apakah Anda juga memeriksa bagian itu di server penerbit untuk memastikan tidak ada yang terdaftar? Jika Anda menemukannya, Anda dapat mencoba menghapusnya secara manual:

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

Tetapi dengan asumsi mereka semua benar-benar hilang, coba ini pada database penerbit:

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

Marilah kita tahu bagaimana kelanjutannya. Replikasi ketika masuk ke negara ini mengacaukan saya dan DBA baik lainnya tidak ada hubungannya dengan menjadi pengembang sama sekali :-)

Cody Konior
sumber
Terima kasih untuk sarannya. Perintah sp_dropsubscription mengeluh bahwa tidak ada langganan. Perintah sp_droppublication mengeluh bahwa replikasi tidak diaktifkan - yang membawa saya pada apa yang tampaknya menjadi solusi.
TallGuy
Bagi saya, perintah sp_removedbreplication bekerja hampir sepanjang waktu setiap kali saya harus menghapus replikasi dengan paksa.
SQLPRODDBA
0

Satu-satunya cara saya dapat menyingkirkan artefak replikasi hantu adalah dengan menghentikan langganan, artikel, publikasi. Jika masih ada langganan hantu, kemudian buat ulang publikasi termasuk pelanggan hantu. Ini tampaknya bekerja dengan versi lama khususnya.

Edwina Montague-Martin
sumber
0

inilah yang biasanya saya lakukan ketika saya memiliki publikasi yang kacau.

itu agak jelek tetapi telah bekerja untuk saya pada banyak kesempatan di lingkungan yang berbeda. apa yang menyebabkannya? yang kadang-kadang sulit untuk mencari tahu, yang terbaik kadang-kadang untuk memulai dari awal, tapi bahkan untuk itu Anda perlu untuk membersihkan allyang residualsdari publikasi saat ini yang rusak.

hanya untuk memasukkannya ke dalam konteks:

Ini yang saya lihat dari monitor replikasi:

masukkan deskripsi gambar di sini

dan ketika saya menggunakan monitor replikasi saya sendiri menggunakan 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 

Anda dapat melihat 2 baris pada kotak terakhir di bawah ini - dan yang satu tidak boleh ada di sana:

masukkan deskripsi gambar di sini

sama ketika saya menggunakan skrip ini:

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

masukkan deskripsi gambar di sini

Pertama, Anda melakukan apa yang ditunjukkan dalam jawaban lain di atas, jika itu berhasil , itu baik-baik saja, kadang-kadang berfungsi, masalah dipecahkan.

itu akan lebih dari itu:

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

Sekarang untuk menyingkirkan sepenuhnya publikasi ini kita akan mulai dengan koneksi ke buscriber, dan kemudian penerbit, dan kemudian distributor sesuai skrip di bawah ini:

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

pada titik ini buat kembali publikasi seperti biasa

lalu pasang snapshot untuk dijalankan

tunggu sampai selesai membuat snapshot

MAYBE YOU DONT NEED TO RUN THE SNAP- coba withoutjalankan dulu, sebagian besar waktu tidak berfungsi, Anda juga dapat menambahkan hanya 1-2 smallartikel ke publikasi sehingga snap berjalan cepat

tetapi jika Anda menjalankan snapshot maka Anda harus menunggu sampai selesai sebelum Anda dapat melanjutkan ke langkah berikutnya - drop the publication

masukkan deskripsi gambar di sini

setelah itu Anda menghasilkan skrip drop that publicationsesuai gambar di bawah ini: masukkan deskripsi gambar di sini

semoga setelah itu, ketika Anda menjalankan skrip asli kami di atas , atau melihat monitor replikasi Anda tidak akan melihat publikasi yang salah, hanya yang baik, dalam kasus saya hanya satu:

masukkan deskripsi gambar di sini

Marcello Miorelli
sumber
-1

Saya memiliki masalah yang sama pada kotak pra-produksi saya, perintah

exec sp_cleanupdbreplication

tampaknya telah bekerja untuk membersihkan entri langganan palsu ...

CARLA
sumber