วิธีการแก้ไขการจำลองแบบ messed up บน MS SQL Server


11

ฉันกู้คืนฐานข้อมูลจากข้อมูลสำรอง ฐานข้อมูลใช้การจำลองแบบเพื่อเผยแพร่ไปยังเซิร์ฟเวอร์อื่น สมมติว่าการคืนค่าฐานข้อมูลจะทำให้การจำลองแบบแตกหักฉันพยายามลบการจำลองและสร้างใหม่อีกครั้ง (เรามีสคริปต์เพื่อสร้างใหม่อีกครั้งตั้งแต่เริ่มต้น) ฉันไม่แน่ใจว่าสิ่งที่ฉันทำ แต่ตอนนี้มันอยู่ในสภาพที่ยุ่งเหยิงอย่างสมบูรณ์และฉันไม่สามารถแก้ไขได้

ก่อนอื่นฉันพยายามกำจัดการสมัครรับข้อมูล (บนเซิร์ฟเวอร์ผู้เผยแพร่):

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

ดูเหมือนว่าจะใช้งานได้ SELECT * FROM syssubscriptionsไม่แสดงผลลัพธ์ ค้นหาเซิร์ฟเวอร์สมาชิก SSMS> {SubscriberServer}> การจำลองแบบ> การสมัครสมาชิกท้องถิ่น - การสมัครสมาชิกไม่ได้อยู่ที่นั่น

ดังนั้นฉันจึงพยายามลบสิ่งพิมพ์ SSMS> {Server}> การจำลองแบบ> Local Publications> {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 Agent และฉันได้รับข้อยกเว้น SQL ภายในนี้:

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

ดังนั้นฉันจึงลองวิธีอื่นในการลบบทความ, DELETE FROM sysarticles. ดูเหมือนว่าจะใช้งานได้แล้ว - ตอนนี้ฉันได้ลบบทความออกไปแล้ว แต่ฉันยังคงเหมือนเดิม 'ไม่สามารถวางสิ่งพิมพ์ได้เนื่องจากมีการสมัครรับข้อมูลอย่างน้อยหนึ่งรายการสำหรับสิ่งพิมพ์นี้' เมื่อฉันพยายามลบสิ่งพิมพ์

ฉันได้รีสตาร์ท SQL Server ด้วย - ไม่ช่วย

ฉันไม่รู้ว่าเกิดอะไรขึ้นที่นี่และฉันจะแก้ไขได้อย่างไร

BTW นี่คือสิ่งที่จะเกิดขึ้นเมื่อคุณให้นักพัฒนาซอฟต์แวร์ที่รู้จักพอที่จะเป็นอันตรายต่อคีย์ในฐานข้อมูล โชคดีที่นี่ไม่ใช่สภาพแวดล้อมการผลิต ...

คำตอบ:


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_dropsubscription บ่นว่าไม่มีการสมัครสมาชิกอยู่ ดังนั้นฉันจึงลองใช้คำสั่ง sp_droppublication นี้บ่นว่าการจำลองแบบไม่ได้เปิดใช้งานในฐานข้อมูล ดังนั้นฉันจึงเปิดใช้งานและรันคำสั่งอีกครั้ง คราวนี้มันบ่นว่าไม่มีสิ่งพิมพ์ ฉันรีเฟรชโหนด Local Publications ใน SSMS และพอมันหายไป ฉันรันสคริปต์การตั้งค่าการจำลองแบบสร้างสแนปชอตใหม่และทุกสิ่งทำงานได้อย่างถูกต้อง จอย!

ฉันไม่แน่ใจ 100% ว่าการปิดใช้งานและเปิดใช้งานการจำลองแบบเป็นสิ่งที่แก้ไขปัญหาได้จริง แต่ก็คุ้มค่าที่จะลองหากการจำลองแบบเกิดความสับสน


ยอดเยี่ยมอ่านสำหรับมือใหม่ ปลอดภัยหรือไม่ที่จะบอกว่าคุณควรปิดใช้งานการจำลองแบบก่อนที่จะกู้คืนฐานข้อมูลหรือไม่
Keith Rivera

แน่นอนว่าฉันจะลองอีกครั้งในครั้งต่อไป - จากสิ่งที่ฉันได้อ่านการจำลองแบบไม่ควรต้องถูกพัดหายไปและสร้างขึ้นใหม่อย่างสมบูรณ์ ปิดใช้งานการจำลอง, คืนค่าฐานข้อมูล, เปิดใช้งานการจำลอง, กดสแนปชอตใหม่ ตราบใดที่บทความยังมีผลอยู่ก็ควรไปต่อ ควรลองต่อไป ...
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_dropsubscription บ่นว่าไม่มีการสมัครสมาชิกอยู่ คำสั่ง sp_droppublication บ่นว่าการจำลองแบบไม่ได้เปิดใช้งาน - ซึ่งทำให้ฉันไปยังสิ่งที่ดูเหมือนจะเป็นวิธีการแก้ปัญหา
TallGuy

สำหรับฉันคำสั่ง sp_removedbreplication ทำงานได้เกือบทุกครั้งที่ฉันต้องเอาการจำลองแบบออกแรง
SQLPRODDBA

0

วิธีเดียวที่ฉันสามารถกำจัดวัตถุจำลองแบบ phantom ได้คือการทิ้งการสมัครสมาชิกบทความสิ่งพิมพ์ หากยังมีการสมัครสมาชิก phantom ให้สร้างสิ่งพิมพ์ใหม่รวมถึงผู้สมัครสมาชิก phantom ดูเหมือนว่าจะทำงานกับเวอร์ชันเก่าโดยเฉพาะ


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 บรรทัดในช่องสุดท้ายด้านล่าง - และหนึ่งบรรทัดไม่ควรอยู่ที่นั่น:

ป้อนคำอธิบายรูปภาพที่นี่

เหมือนกันเมื่อฉันใช้สคริปต์นี้:

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

ตอนนี้เพื่อกำจัดสิ่งพิมพ์นี้อย่างสมบูรณ์เราจะเริ่มต้นด้วยการเชื่อมต่อกับ buscriber แล้วผู้เผยแพร่และจากนั้นจัดจำหน่ายตามสคริปต์ด้านล่าง:

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