การจัดการกับช่วงข้อมูลเฉพาะตัวสำหรับการจำลองแบบของทรานแซคชัน


9

ฉันสังเกตเห็นว่าเมื่อคุณตั้งค่าการจำลองแบบของทรานแซคชัน SQL Server จะตั้งค่าการจัดการช่วงข้อมูลประจำตัวเป็นคู่มือ สิ่งนี้หมายความว่าในฐานข้อมูลการสมัครสมาชิกของฉันเมื่อฉันพยายามที่จะแทรกระเบียนใหม่ลงในตารางที่มี PK เป็นคอลัมน์ข้อมูลประจำตัวมันจะทำให้ฉันมีข้อผิดพลาดและบอกว่ามันพยายามแทรก PK ของ "1", "2 "," 3 "ฯลฯ นี่เป็นเพราะค่าข้อมูลประจำตัวปัจจุบันสำหรับคอลัมน์ข้อมูลประจำตัวทั้งหมดของผู้สมัครสมาชิกจะได้รับการรีเซ็ตเป็นค่าเริ่มต้น (ปกติ 1) แทนที่จะอยู่ในสิ่งที่เป็นอยู่ของผู้เผยแพร่

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

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

ข่าวสารเกี่ยวกับ 21231, ระดับ 16, สถานะ 1, กระบวนงาน sp_MSrepl_addarticle, บรรทัด 2243
การสนับสนุนช่วงข้อมูลเฉพาะตัวอัตโนมัติมีประโยชน์สำหรับสิ่งพิมพ์ที่อนุญาตให้มีการอัพเดตผู้สมัครสมาชิกเท่านั้น

มีวิธีใดบ้างที่ฉันสามารถแก้ไขปัญหานี้ได้ ฉันต้องการนำเสนอการจำลองแบบนี้ไปยัง SQL Server ราวกับว่าเป็นแบบอ่านอย่างเดียวในตอนท้ายสมาชิกเนื่องจากฉันไม่ได้วางแผนที่จะทำการอัปเดตที่จะถูกส่งกลับไปยังผู้เผยแพร่แต่ฉันต้องการทำการปรับปรุงชั่วคราวที่ จะถูกลบก่อนการจำลองแบบถัดไป

ฉันยังได้พิจารณาแล้วเห็นว่าการทำแบบจำลองภาพรวมอาจจะเป็นวิธีการที่เหมาะสมมากกว่าการทำแบบจำลองการทำธุรกรรมสำหรับรูปแบบการใช้ของฉัน แต่ปัญหาก็คือว่าการจำลองแบบ snapshot ต้องส่งยี้ทั้ง DBปรับปรุงทุกเดียว; เนื่องจากฉันวางแผนที่จะสำรองข้อมูลฐานข้อมูลทันทีหลังจากการจำลองแบบล่าสุดฉันไม่ควรต้องทำการถ่ายโอนทั้งหมดนั้นทุกครั้ง เพียงแค่การเปลี่ยนแปลงตั้งแต่ครั้งที่แล้ว


คุณใช้ SQL Server เวอร์ชันใดอยู่ คุณสามารถกำหนดตารางใหม่ได้ไหม?

2008 r2 ผมไม่เห็นว่าการกําหนดตารางจะแก้ปัญหานี้ ...
Jez

ฉันคิดว่าวิธีการแก้ปัญหาโดยใช้ SEQUENCE แต่สำหรับ SQL 2012 เท่านั้น

2
Is there any way I can get round this problem?คุณต้องตั้งค่าคอลัมน์ข้อมูลประจำตัวไม่ใช่สำหรับการจำลองโดยใช้sys.sp_identitycolumnforreplicationสำหรับ sql server 2005 ขึ้นไป คุณไม่จำเป็นต้องทำการ resnapshot บทความของคุณเมื่อคุณเปลี่ยนคอลัมน์ข้อมูลประจำตัวเพื่อใช้ในการทำซ้ำ ไม่ต้องทำโดยใช้ GUI
Kin Shah

มันถูกทำเครื่องหมายว่าไม่ใช่สำหรับการจำลอง นั่นเป็นปัญหา - SQL Server ไม่ได้คัดลอกข้อมูลประจำตัวดังนั้นสมาชิกจะเริ่มต้นที่ 1
Jez

คำตอบ:


3

สมมติว่าผู้เผยแพร่ของคุณใช้รหัสประจำตัว int ที่เริ่มต้นที่ 1 คุณสามารถออก DBCC CHECKIDENT('dbo.mytable', RESEED, -2147483648) ที่สมาชิกได้ จากนั้นคุณสามารถใช้ช่วงตั้งแต่ -2147483648 ถึง 0 เพื่อระงับ "เดลตาชั่วคราว" ของคุณ


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

ทำไมคุณต้องซิงโครไนซ์ข้อมูลเฉพาะตัวด้วยตนเอง เพียงแค่เขียนโพรซีเดอร์ที่เก็บไว้ที่ผู้สมัครสมาชิกที่รันตัวตรวจสอบสำหรับแต่ละตารางที่คุณกำลังเก็บเดลต้าชั่วคราวและเรียกใช้หลังจากสแน็ปช็อตเสร็จสิ้นการใช้งาน ตัวแทนการแจกจ่ายจะแทรกการเปลี่ยนแปลงเมื่อเกิดขึ้นในช่วงข้อมูลเฉพาะตัว "ของจริง" และการเปลี่ยนแปลงที่ทำกับสมาชิกโดยตรงจะอยู่ในช่วงลบ
เลียม Confrey

1

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

synchronize databases with TransSynchronizationAgent

equivalentTablesNotFound is a list of strings
for each table in publisher tables:
    try:
        check table identity value (this is via functionality provided by .NET's Microsoft.SqlServer.Management.Smo.Server class)
        parse identity value as integer to newIdentity
        if the table's identity value was NULL, skip to next loop iteration
        (HACK) increment newIdentity value by 1
        if there is no subscriber table with the same name as this one:
            record its name in equivalentTablesNotFound and skip to next loop iteration
        set subscriber table with same name's identity value to newIdentity using TSQL: DBCC CHECKIDENT ("tableName", newIdentity)
    catch:
        if exception shows that the error was because the table doesn't have an identity column, drop the exception

if equivalentTablesNotFound has more than zero entries, warn about tables on publisher without an equivalent name on subscriber

ดูเหมือนว่าจะทำงานได้ดี HACK บิตเป็นเพราะถึงแม้ว่าโดยค่าเริ่มต้นและด้วยตารางทั้งหมดของฉันค่าตัวตนจะเพิ่มขึ้นทีละหนึ่ง แต่ก็สามารถกำหนดค่าได้แตกต่างกันดังนั้นในทางเทคนิคที่นี่คุณควรศึกษาว่าการเพิ่มมูลค่าตัวตนในตารางผู้เผยแพร่โฆษณา วิธีการเดียวกัน.


0

วิธีที่ฉันชอบในการจัดการนี่คือทำดังต่อไปนี้:

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

ข เปลี่ยนชื่อตารางที่มีอยู่ของคุณที่สอง

exec sp_rename '[CurrentTable]', '[BackupTableName]'

ค. สร้างตารางของคุณใหม่ด้วยชุดตัวระบุ

CREATE TABLE [CurrentTable]
(
   ID INT NOT NULL IDENTITY(1,1), 
   OtherField VARCHAR(10) NULL,
   ....
)

d กรอกข้อมูลในตารางของคุณ (จาก [BackupTableName]) ด้วย SET IDENTITY_INSERT

SET IDENTITY_INSERT [CurrentTable] ON
INSERT INTO [CurrentTable] (ID, OtherField, ...)
SELECT ID, OtherField, ....
FROM [BackupTableName]
SET IDENTITY_INSERT [CurrentTable] OFF

เมื่อคุณมีข้อ จำกัด ของตัวตนบนฐานข้อมูลแล้วคุณสามารถทำการจำลองแบบที่กำหนดเอง (เช่น: เปลี่ยน pro repl repl ของคุณเป็น SET IDENTITY_INSERT [TableName] ON หรือคุณสามารถตั้งค่าสถานะ NOT FOR REPLICATION บนตาราง (ซึ่งบอก SQL server ว่า หากผู้ใช้เชื่อมต่อเป็น บริษัท ตัวแทนการจำลองที่คาดว่าค่าตัวตนที่จะมาด้วย) ( ผมชอบวิธีการจำลองแบบกำหนดเองตามที่มันทำให้ผมมีความยืดหยุ่นมากขึ้น )

อี ปรับเปลี่ยนขั้นตอนการจำลองแบบที่เก็บไว้ของคุณแทรก (โดยปกติชื่อ sp_MSins_CurrentTable) เพื่อแทรกโดยใช้SET IDENTITY INSERT

ALTER procedure [dbo].[sp_MSins_CurrentTable]
    @c1 int, @c2 varchar(50), ...
as
begin
    /* allow replication to insert values for IDENTITY */
    SET IDENTITY_INSERT [CurrentTable] ON
    insert into [CurrentTable]
        ([ID], [OtherField], ...)
    values
        (@c1, @c2, ...)
    /* now turn off Identity insert */
    SET IDENTITY_INSERT [CurrentTable] OFF
end

ฉ ตอนนี้คุณสามารถรีสตาร์ทตัวแทนการจำลองแบบของคุณ


1
ฮ่า ๆ เมื่อเทียบกับการใช้DBCC CHECKIDENTวิธีนี้เป็นงานจำนวนมาก
Jez

@Jez คุณจะต้องสร้างตารางใหม่ (ที่มีตัวตน) เพื่อที่จะเรียกใช้ DBEC CHECKIDENT ... ภาพรวมของการจำลองแบบจะสร้างตารางโดยไม่มีข้อ จำกัด IDENTITY (ขึ้นอยู่กับ q ของคุณฉันจะบอกว่า CHECKIDENT DBCC ชนะ 'ทำงาน)
Andrew Bickerton

FYI มันไม่ทำงานและการจำลองแบบไม่สร้างตารางที่มี จำกัด ของตัวระบุ ...
Jez

@Jez คุณตั้งค่าการจำลองแบบประเภทใด (ถ้าคุณตั้งค่าเป็น MERGE ที่จะเกิดขึ้นสำหรับการทำธุรกรรมมักจะไม่ถึงแม้ว่าการจำลองจะปรับแต่งได้สูงถ้าคุณไม่ใช้ GUI)
Andrew Bickerton

การทำธุรกรรม อย่างที่ฉันบอกว่ามีตัวตนอยู่ แต่ค่าตัวตนปัจจุบันถูกรีเซ็ตเป็นค่าเมล็ด (1)
Jez
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.