लेन-देन प्रतिकृति के लिए पहचान श्रेणियों से निपटना


9

मैंने देखा है कि जब आप एक ट्रांसेक्शनल प्रतिकृति स्थापित करते हैं, तो SQL सर्वर मैन्युअल रूप से पहचान रेंज प्रबंधन सेट करेगा। इसका मतलब यह है कि मेरे सदस्यता डेटाबेस में, जब मैं एक तालिका में एक नया रिकॉर्ड सम्मिलित करने की कोशिश करता हूं, जिसका पीके एक पहचान स्तंभ है, तो यह मुझे एक त्रुटि देगा और कहेगा कि इसने "1", "2" का पीके डालने की कोशिश की "," 3 ", आदि इसका कारण यह है कि सब्सक्राइबर पर सभी पहचान कॉलमों के लिए वर्तमान पहचान मूल्य बीजक मूल्य (आमतौर पर 1) पर रीसेट हो जाता है बजाय इसके कि यह प्रकाशक पर क्या था।

मैं समझता हूं कि SQL सर्वर ऐसा क्यों करता है - आपको सब्सक्राइबर टेबल को केवल पढ़ने के लिए छोड़ना चाहिए। हालाँकि, मेरा परिदृश्य थोड़ा अपरंपरागत है - मैं समय-समय पर प्रतिकृति के माध्यम से अपने ग्राहक को अपडेट करता हूं, उस DB का तत्काल बैकअप बनाता हूं, फिर मैं उस ग्राहक को कुछ अपडेट करना चाहता हूं जिसे WON'T को प्रकाशक के पास वापस नहीं भेजा जाएगा, फिर जब मैं ग्राहक को फिर से अपडेट करने जाता हूं, तो मैं इसके डेटाबेस को पहले के बैकअप से पुनर्स्थापित करता हूं और नवीनतम अपडेट खींचता हूं। क्योंकि मैं इन अद्यतनों के बीच में ग्राहक को अपडेट करना चाहता हूं (यदि आप करेंगे तो अस्थायी अस्थायी), मुझे काम करने के लिए पहचान कॉलम की आवश्यकता है और दोहराया जाने पर 1 पर रीसेट करने की नहीं।

मैंने अपना प्रकाशन सेट करते समय स्वचालित पहचान रेंज प्रबंधन को चालू करने का प्रयास किया, लेकिन जब मुझे प्रकाशन में तालिका जोड़ने की कोशिश की जाती है, तो बस मुझे निम्न त्रुटि मिलती है:

Msg 21231, स्तर 16, राज्य 1, प्रक्रिया sp_MSrepl_addarticle, लाइन 2243
स्वचालित पहचान रेंज समर्थन केवल उन प्रकाशनों के लिए उपयोगी है जो ग्राहकों को अपडेट करने की अनुमति देते हैं।

क्या कोई रास्ता है जिससे मुझे इस समस्या का सामना करना पड़ सकता है? मैं एसक्यूएल सर्वर के लिए इस प्रतिकृति को प्रस्तुत करना चाहता हूं जैसे कि यह केवल सब्सक्राइबर अंत में पढ़ा गया था क्योंकि मैं अपडेट करने की योजना नहीं बनाता हूं जिसे प्रकाशक को वापस धकेल दिया जाएगा , लेकिन मैं अस्थायी अपडेट करना चाहता हूं जो अगले प्रतिकृति से पहले मिटा दिया जाएगा।

मैंने यह भी माना है कि स्नैपशॉट प्रतिकृति मेरे उपयोग पैटर्न के लिए ट्रांसेक्शनल प्रतिकृति की तुलना में अधिक उपयुक्त विधि हो सकती है, लेकिन परेशानी यह है कि स्नैपशॉट प्रतिकृति को पूरे darn DB को हर एक अपडेट भेजने की आवश्यकता होती है ; क्योंकि मैं नवीनतम प्रतिकृति के बाद DB का तत्काल बैकअप लेने की योजना बना रहा हूं, मुझे हर बार उस पूरे स्थानांतरण को करने की आवश्यकता नहीं है; पिछली बार से सिर्फ बदलाव।


SQL सर्वर के किस संस्करण का आप उपयोग कर रहे हैं? क्या आप टेबल को फिर से परिभाषित कर सकते हैं?

2008 आर 2। मैं नहीं देखता कि टेबल को फिर से परिभाषित करने से इस समस्या का समाधान कैसे होगा ...
Jez

मैं एक समाधान का उपयोग करने के बारे में सोच रहा था, लेकिन यह केवल एसक्यूएल 2012 के लिए है।

2
Is there any way I can get round this problem?आप के रूप में सेट पहचान स्तंभ के लिए है नहीं प्रतिकृति के लिए का उपयोग कर sys.sp_identitycolumnforreplication के लिए SQL सर्वर 2005 और ऊपर। जब आप प्रतिकृति के लिए पहचान कॉलम नहीं बदलते हैं तब भी आपको अपने लेखों को फिर से जारी नहीं करना पड़ता है। बस जीयूआई का उपयोग न करें।
परिजन शाह

यह पहले से ही प्रतिकृति के रूप में चिह्नित नहीं है। यह मूल रूप से समस्या है - SQL सर्वर ग्राहक पर पहचान की जानकारी की नकल नहीं करता है, यह 1 से अधिक शुरू होता है
Jez

जवाबों:


3

मान लें कि आपका प्रकाशक एक ऐसी पहचान का उपयोग कर रहा है जो 1 से शुरू होती है, तो आप DBCC CHECKIDENT('dbo.mytable', RESEED, -2147483648) ग्राहक को जारी कर सकते हैं । तब आप अपने "अस्थायी डेल्टा" को रखने के लिए -2147483648 से लेकर 0 तक की रेंज का उपयोग कर सकते हैं।


यह वह समाधान है जिसके साथ मैं आया था, लेकिन इसका मतलब अभी भी मेरा कोड प्रकाशक और ग्राहक से जुड़ रहा है और पहचान को मैन्युअल रूप से सिंक्रनाइज़ कर रहा है। मुझे उम्मीद थी कि इसे करने के लिए एक और अधिक स्वचालित तरीका था।
जीन

आपको मैन्युअल रूप से पहचान को सिंक्रनाइज़ करने की आवश्यकता क्यों होगी? बस उस सब्सक्राइबर पर एक संग्रहीत कार्यविधि लिखें, जो प्रत्येक तालिका के लिए चेक-इन चलाता है जिसे आप अस्थायी डेल्टा में स्टोर कर रहे हैं, और स्नैपशॉट समाप्त होने के बाद इसे चलाएं। वितरण एजेंट परिवर्तनों को सम्मिलित करेगा क्योंकि वे "वास्तविक" पहचान सीमा में होते हैं, और ग्राहक को सीधे किए गए परिवर्तन नकारात्मक सीमा में होंगे।
लियाम कन्फ्रे

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

इसे संभालने के लिए मेरा पसंदीदा तरीका निम्नलिखित है:

ए। सबसे पहले अपने प्रतिकृति एजेंट को बंद करें (ताकि आपको अपने सब्सक्राइबर DB में कोई नया डेटा नहीं मिल रहा है)

ख। दूसरा अपनी मौजूदा तालिका का नाम बदलें

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

सी। IDENTITY सेट के साथ अपनी तालिका को फिर से बनाएं

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

घ। SET IDENTITY_INSERT के साथ अपनी तालिका ([BackupTableName] से) को बैकफ़िल करें

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

एक बार जब आपके पास आपके DB पर IDENTITY बाधा आ जाती है, तो आप या तो कस्टम प्रतिकृति कर सकते हैं (यानी: अपना इन्सर्ट उत्तर बदलकर SET IDENTITY_INSERT [TableName] पर खरीदें या आप टेबल पर REPLICIC ध्वज के लिए सेट नहीं कर सकते हैं (जो SQL सर्वर को बताता है) यदि कनेक्टिंग उपयोगकर्ता प्रतिकृति एजेंट है, तो आपूर्ति की जाने वाली पहचान मूल्य की अपेक्षा करें) ( मैं कस्टम प्रतिकृति दृष्टिकोण पसंद करता हूं, क्योंकि यह मुझे अधिक लचीलापन देता है )

इ। अपनी प्रविष्टि प्रतिकृति संग्रहीत कार्यविधि (आमतौर पर 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 आपको DBCC CHECKIDENT को चलाने के लिए तालिका (IDENTITY के साथ) को फिर से बनाना होगा ... प्रतिकृति का एक स्नैपशॉट IDENTITY बाधा के साथ तालिका बना देगा (आपके q के आधार पर मैं कहूंगा DBCC CHECKIDENT जीता 'टी वर्क)
एंड्रयू बिकर्टन

FYI करें यह काम किया है और प्रतिकृति पहचान की कमी के साथ तालिका बनाता है ...
Jez

@ क्या आपने किस प्रकार की प्रतिकृति स्थापित की है? (यदि आप इसे MERGE के रूप में स्थापित करते हैं, तो ट्रांसकेशनल के लिए, यह आमतौर पर नहीं होता है, हालांकि प्रतिकृति अत्यधिक अनुकूलन योग्य है यदि आप GUI का उपयोग नहीं करते हैं)
एंड्रयू बिकर्टन

लेन-देन की। जैसा कि मैंने कहा कि पहचान है, लेकिन वर्तमान पहचान मूल्य बीज मूल्य (1) पर रीसेट है।
Jez
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.