2010-04-12 11 views
5

मेरे पास ऐसी स्थिति है जहां दो व्यक्ति दो अलग-अलग कंप्यूटरों से उसी क्रम (एमएस एसक्यूएल डेटाबेस में संग्रहीत) पर काम कर सकते हैं। इस मामले में डेटा हानि को रोकने के लिए, जहां कोई व्यक्ति अपनी ऑर्डर की प्रतिलिपि पहले सहेज लेगा, और उसके बाद थोड़ी देर बाद दूसरी अपनी प्रतिलिपि को सहेज लेगी और पहले ओवरराइट करेगी, मैंने के खिलाफ एक चेक जोड़ा है पिछला सहेजा फ़ील्ड (डेटाटाइम) बचत।एमएस एसक्यूएल डेटाटाइम सटीक समस्या

कोड इस तरह मोटे तौर पर दिखता है:

private bool orderIsChangedByOtherUser(Order localOrderCopy) 
{ 
    // Look up fresh version of the order from the DB 
    Order databaseOrder = orderService.GetByOrderId(localOrderCopy.Id); 

    if (databaseOrder != null && 
     databaseOrder.LastSaved > localOrderCopy.LastSaved) 
    { 
     return true; 
    } 
    else 
    { 
     return false; 
    } 
} 

इस समय के सबसे अधिक के लिए काम करता है, लेकिन मैं एक छोटी सी बग मिल गया है।

तो orderIsChangedByOtherUser रिटर्न झूठी, स्थानीय प्रति अपनी lastSaved वर्तमान समय पर अद्यतन और उसके बाद डेटाबेस से कायम किया जा होगा। स्थानीय प्रतिलिपि में का अंतिम स्थान का मूल्य और डीबी अब समान होना चाहिए। हालांकि, अगर orderIsChangedByOtherUser फिर से चलाया जाता है, तो कभी-कभी सत्य लौटाता है, भले ही किसी अन्य उपयोगकर्ता ने डीबी में बदलाव नहीं किए हैं।

जब दृश्य स्टूडियो में डीबगिंग, databaseOrder.LastSaved और एक ही मूल्य है दिखाई देते हैं localOrderCopy.LastSaved, लेकिन जब करीब देख वे कुछ समय में कुछ मिलीसेकेंड से भिन्न होते हैं।

मैं एसक्यूएल में दिनांक के लिए मिलीसेकंड परिशुद्धता पर एक अल्प सूचना के साथ this article पाया:

एक और समस्या यह है कि एसक्यूएल सर्वर 3.33 मिलीसेकेंड (0. 00,333 सेकंड) के एक परिशुद्धता के साथ भंडार DATETIME है।

समाधान मैं इस समस्या के बारे में सोच सकता हूं, दो डेटाटाइम की तुलना करना और उन्हें 10 मिलीसेकंड कहने से कम भिन्न होने पर विचार करना चाहिए।

मेरा प्रश्न तब है: क्या एमएस एसक्यूएल में दो डेटाटाइम मानों की तुलना करने के लिए कोई बेहतर/सुरक्षित तरीका है यह देखने के लिए कि क्या वे बिल्कुल समान हैं?

+0

पर सेट है, तो बस निर्दिष्ट करने के लिए: मेरे पास * lastSaved * फ़ील्ड के प्रकार को बदलने का विकल्प नहीं है, इसलिए मुझे डेटाटाइम के साथ चिपकना होगा। – Nailuj

उत्तर

4

मैं तुम्हें कहा था कि आप परिवर्तन नहीं कर सकते पता है, लेकिन अगर यह केवल है अनुकूलता & अपने 2008 का उपयोग कर बनाए रखने के लिए आप DATETIME2 को lastSaved क्षेत्र को बदल सकता है (जो DATETIME साथ पूरी तरह से संगत है) और जो दोनों के SYSDATETIME() का उपयोग बहुत अधिक सटीकता है।

+0

मुझे डेटाटाइम 2 के बारे में पता नहीं था। मेरे परीक्षण सर्वर कम से कम SQL Server 2008 चला रहे हैं, ताकि वास्तव में एक विकल्प हो। बस यह सुनिश्चित करना है कि सिस्टम का उपयोग करने वाले सभी भी 2008 पर हैं ... धन्यवाद :) – Nailuj

0

आप डेटाटाइम फ़ील्ड के बजाए अंतिम संपादन तिथि देखने के लिए टाइमस्टैम्प फ़ील्ड का उपयोग कर सकते हैं? (एसक्यूएल 2008 में यह अब RowVersion है)

+0

एक संभावना हो सकती है, लेकिन मेरे पास अंतिम सहेजे गए फ़ील्ड के प्रकार को बदलने का विकल्प नहीं है। – Nailuj

+0

आपको नहीं करना है। इसके लिए एक अतिरिक्त क्षेत्र जोड़ें। फिर पीके और पंक्ति संस्करण फ़ील्ड दोनों को जांचने के लिए अद्यतन एसपी को संशोधित करें। यदि पंक्ति संस्करण बदल गया है तो आपको 0 पंक्तियां प्रभावित होंगी। –

0

आपको यह सुनिश्चित करना होगा कि आपका समय सटीक रेखाएं बढ़ जाए - यह सी # पक्ष पर उचित तर्क प्राप्त करने के लिए अधिकतर करने योग्य है, वास्तव में डेटटाइम में मूल के तहत सटीकता को कम करने के लिए ऑब्जेक्ट - मूल रूप से सुअर बनाते हैं, उदाहरण के लिए आप सभी परतों में हमेशा सेकेंड में, कम नहीं होते हैं।

यदि आप इसे सही तरीके से करते हैं, तो सभी परतों में टाइमस्टैम्प तुरंत तुलनीय होगा।

2

आप अपनी ऑर्डर तालिका में एक पूर्णांक संशोधन फ़ील्ड जोड़ सकते हैं। प्रत्येक बार जब कोई उपयोगकर्ता आदेश सहेजता है तो आप एक संशोधन को बढ़ाते हैं। फिर यह जांचना आसान है कि किसी ने ऑर्डर बदल दिया है या यदि उपयोगकर्ता जो ऑर्डर को सहेजना चाहता है, वह नवीनतम संशोधन पर है।

1

जब तक आप SQL 2005 के भीतर हों और सटीकता समस्या हमेशा वहां रहेगी, एक सेकंड के 1/300 वें या 3.33ms से अधिक सटीक नहीं।

सटीकता की कमी के बावजूद आप एक दोषपूर्ण दौड़ की स्थिति प्रोग्रामिंग कर रहे हैं जहां दोनों उपयोगकर्ता त्वरित उत्तराधिकार में डेटाबेस पर अभी भी लिख सकते हैं लेकिन दोनों को सशक्त माना जा सकता है। सटीकता की कमी इसके कारण होने की संभावना बढ़ जाती है, जब तक कि चेक और उसके बाद के विचारों को उसी 3-4 एमएस के भीतर लिया जाता है।

किसी भी लिखने के बाद जांच करने का कोई भी प्रयास इस समस्या को पीड़ित करता है, और आपको या तो आशावादी लॉकिंग के परिणामों को स्वीकार करना होगा, लॉकिंग को निराशा में बदलना होगा या लॉकिंग को सही तरीके से संभालने के लिए सैमफोर प्रकार की रणनीति के कुछ रूपों को लागू करना होगा।

+0

मुझे संभावित रूप से त्रुटिपूर्ण तर्क के बारे में पता है, लेकिन कई पुरानी प्रणालियों के साथ ही इसे किसी के साथ रहना पड़ता है। मुझे एक छोटी उम्मीद थी कि वहां एक रास्ता हो सकता है, लेकिन मुझे लगता है कि हम 0.33 एमएमएस सटीकता के साथ रह सकते हैं। – Nailuj

0

संभावित रूप से ऐसा करने का एक और तरीका है।

स्थानीय मशीन से "अंतिम सहेजा गया" में गुजरने के बजाय, अद्यतन संग्रहीत प्रक्रिया को संशोधित करें। असाइन करें LastSaved = getdate() फिर अंतिम सहेजे गए मूल्य (और आईडी के रूप में किसी भी अन्य परिणाम) का मान वापस करें, और उस परिणाम के साथ क्लाइंट पर अंतिम सहेजे गए समय को अपडेट करें।

इसके लिए दो स्पष्ट फायदे हैं। एक यह है कि आपकी डेटटाइम सटीकता संरक्षित है। दूसरी बात यह है कि किसी भी नेटवर्क विलंबता और स्थानीय घड़ी बहाव के मुद्दों से पीड़ित होने की बजाय दिनांक और समय अब ​​सर्वर के अनुरूप है।

हम आमतौर पर सीआरयूडी संचालन के लिए ऑटो जेनरेटेड एसपी का उपयोग करते हैं, और टेबल आमतौर पर "निर्मित/अंतिम अद्यतन" और "निर्मितबी/अंतिम अद्यतन बी" जोड़े जोड़े जाते हैं जहां सर्वर पर दिनांक सेट होते हैं, और "द्वारा" मान पास किए जाते हैं, और यदि NULL System_User

संबंधित मुद्दे