SELECT-UPDATE पैटर्न का उपयोग करते समय संगामिति प्रबंधित करना


25

मान लीजिए कि आपके पास निम्नलिखित कोड हैं (कृपया ध्यान दें कि यह बहुत ही भयानक है):

BEGIN TRAN;
DECLARE @id int
SELECT @id = id + 1 FROM TableA;
UPDATE TableA SET id = @id; --TableA must have only one row, apparently!
COMMIT TRAN;
-- @id is returned to the client or used somewhere else

मेरी नजर में, यह ठीक से संगामिति का प्रबंधन नहीं कर रहा है। सिर्फ इसलिए कि आपके पास एक लेन-देन है, इसका मतलब यह नहीं है कि आपके अपडेट स्टेटमेंट में आने से पहले कोई और उस मूल्य को नहीं पढ़ेगा जो आपने किया था।

अब, जैसा कि कोड को छोड़ रहा है (मुझे पता है कि यह एक एकल कथन के रूप में बेहतर तरीके से या यहां तक ​​कि एक ऑटोइन्क्रिमेंट / पहचान कॉलम का उपयोग करके बेहतर तरीके से नियंत्रित किया जाता है) क्या हैं यह सुनिश्चित करने के तरीके कि इसे सही ढंग से संभालना है और दौड़ की स्थिति को रोकना है जो दो ग्राहकों को समान करने की अनुमति देता है आईडी मूल्य?

मुझे पूरा यकीन है कि WITH (UPDLOCK, HOLDLOCK)SELECT में A जोड़ने से ट्रिक आ जाएगी। Serializable लेनदेन अलगाव स्तर के रूप में अच्छी तरह से काम करने लगता है के बाद से यह इनकार करते हैं किसी और जब तक ट्रॅन खत्म हो गया है आप क्या किया पढ़ने के लिए ( अद्यतन :। यह झूठ है मार्टिन देखें जवाब)। क्या यह सच है? क्या वे दोनों समान रूप से अच्छी तरह से काम करेंगे? क्या एक को दूसरे पर पसंद किया जाता है?

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

इस प्रश्न को लिखने के बाद, मुझे लगता है कि लॉक संकेत बेहतर हैं क्योंकि तब आप केवल उन तालिकाओं को लॉक कर रहे हैं जिनकी आपको आवश्यकता है, लेकिन मैं किसी के इनपुट की सराहना करूंगा।

पुनश्च और नहीं, मैं सबसे अच्छा जवाब नहीं जानता और वास्तव में एक बेहतर समझ प्राप्त करना चाहता हूं! :)


स्पष्टीकरण के लिए: क्या आप 2 ग्राहकों को समान मूल्य को पढ़ने या जारी करने से रोकना चाहते हैं updateजो अप्रचलित डेटा पर आधारित हो सकते हैं? यदि बाद में, आप यह rowversionजांचने के लिए कॉलम का उपयोग कर सकते हैं कि क्या अद्यतन होने के बाद से पंक्ति को बदला नहीं गया है।
a1ex07

हम पहले ग्राहक द्वारा नए मूल्य के लिए अद्यतन किए जाने से पहले पुराने आईडी मूल्य प्राप्त करने वाले दूसरे ग्राहक नहीं चाहते हैं। इसे ब्लॉक करना चाहिए।
EricE

जवाबों:


11

SERIALIZABLEअलगाव स्तर के पहलू को संबोधित करते हुए । हां यह काम करेगा लेकिन गतिरोध जोखिम के साथ।

दो लेनदेन दोनों पंक्ति को समवर्ती रूप से पढ़ने में सक्षम होंगे। वे एक दूसरे को ब्लॉक नहीं करेंगे क्योंकि वे या तो ऑब्जेक्ट Sलॉक या इंडेक्स RangeS-Sलॉक को टेबल संरचना पर निर्भर करेंगे और ये लॉक संगत हैं । लेकिन वे अद्यतन (ऑब्जेक्ट IXलॉक या इंडेक्स RangeS-Uक्रमशः) के लिए आवश्यक लॉक हासिल करने का प्रयास करते समय एक-दूसरे को अवरुद्ध करेंगे, जिससे गतिरोध पैदा होगा।

इसके UPDLOCKबजाय एक स्पष्ट संकेत का उपयोग इस प्रकार गतिरोध से बचने के लिए रीड्स को क्रमबद्ध करेगा।


+1 लेकिन: ढेर तालिकाओं के लिए आप अभी भी अपडेट लॉक के साथ एक रूपांतरण गतिरोध प्राप्त कर सकते हैं: sqlblog.com/blogs/alexander_kuznetsov/archive/2009/03/11/…
AK

विचित्र, @alex। मुझे लगता है कि यह इंजन की एक दौड़ की स्थिति के साथ करने की कोशिश कर रहा है जो वास्तव में UPD लॉक करने से पहले इसे लॉक करने की कोशिश कर रहा है ...
EricE

@ एरिक - एलेक्स के लेख में रूपांतरण गतिरोध को हीप से परिवर्तित किया IXजा रहा Xहै। दिलचस्प बात यह है कि कोई भी पंक्तियाँ योग्य नहीं होती हैं इसलिए कोई भी पंक्ति ताले को कभी बाहर नहीं निकाला जाता है। यह सुनिश्चित नहीं है कि यह Xताला क्यों लेता है ।
मार्टिन स्मिथ

11

मुझे लगता है कि आपके लिए सबसे अच्छा तरीका वास्तव में अपने मॉड्यूल को उच्च संगामिति के लिए उजागर करना और अपने लिए देखना होगा। कभी-कभी केवल UPDLOCK ही पर्याप्त होता है, और HOLDLOCK की कोई आवश्यकता नहीं होती है। कभी-कभी sp_getapplock बहुत अच्छी तरह से काम करता है। मैं यहां कोई कंबल बयान नहीं करूंगा - कभी-कभी एक और सूचकांक, ट्रिगर, या अनुक्रमित दृश्य को जोड़ने से परिणाम बदल जाता है। हमें टेस्ट कोड पर ज़ोर देना होगा और केस के आधार पर अपने लिए देखना होगा।

मैंने यहाँ तनाव परीक्षण के कई उदाहरण लिखे हैं

संपादित करें: इंटर्न के बेहतर ज्ञान के लिए, आप कैलेन डेलानी की किताबें पढ़ सकते हैं। हालाँकि, किताबें किसी अन्य प्रलेखन की तरह ही सिंक से बाहर हो सकती हैं। इसके अलावा, विचार करने के लिए बहुत सारे संयोजन हैं: छह अलगाव स्तर, कई प्रकार के ताले, क्लस्टर किए गए / गैर-अनुक्रमित सूचकांक और जो जानते हैं कि और क्या है। यह बहुत संयोजन है। उसके शीर्ष पर, SQL सर्वर बंद स्रोत है, इसलिए हम स्रोत कोड डाउनलोड नहीं कर सकते हैं, इसे डीबग करें और ऐसा करें - यह ज्ञान का अंतिम स्रोत होगा। अगली रिलीज़ या सर्विस पैक के बाद कुछ भी अधूरा या पुराना हो सकता है।

तो, आपको यह तय नहीं करना चाहिए कि आपके स्वयं के तनाव परीक्षण के बिना आपके सिस्टम के लिए क्या काम करता है। आपने जो भी पढ़ा है, वह यह समझने में आपकी मदद कर सकता है कि क्या चल रहा है, लेकिन आपको यह साबित करना होगा कि आपने जो सलाह पढ़ी है वह आपके लिए काम करती है। मुझे नहीं लगता कि कोई भी आपके लिए यह कर सकता है।


9

इस विशेष मामले में वास्तव में विसंगतियों को रोकने के UPDLOCKलिए एक ताला के अलावा SELECTहोगा। के अलावा HOLDLOCKके रूप में एक अद्यतन ताला लेन-देन की अवधि के लिए आयोजित किया जाता है आवश्यक नहीं है, लेकिन मैं इसे अपने आप अतीत में एक (संभवतः खराब) आदत के रूप में शामिल कबूल।

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

कोई सबसे अच्छा अभ्यास नहीं है। समवर्ती नियंत्रण की आपकी पसंद आवेदन की आवश्यकताओं पर आधारित होनी चाहिए। कुछ अनुप्रयोगों / लेनदेन को निष्पादित करने की आवश्यकता होती है जैसे कि उनके पास डेटाबेस का विशेष स्वामित्व था, हर कीमत पर विसंगतियों और अशुद्धि से बचना। अन्य एप्लिकेशन / लेनदेन एक-दूसरे से कुछ हद तक हस्तक्षेप को सहन कर सकते हैं।

  • एक वेब स्टोर में एक उत्पाद के लिए एक बंद स्टॉक स्तर (<5, 10+, 50+, 100+) को वापस लेना = गंदे पढ़ना (गलत बात नहीं)।
  • उस वेब स्टोर पर स्टॉक लेवल की जाँच करना और कम करना = रिपीटेबल रीड (हमारे पास बेचने से पहले हमारे पास स्टॉक होना चाहिए, हम एक नकारात्मक स्टॉक स्तर के साथ समाप्त नहीं होना चाहिए)।
  • बैंक में मेरे करंट और सेविंग अकाउंट के बीच चल रहा है कैश = सीरियल करने योग्य (मेरे कैश को मिसकॉल करें या गलत न करें!)।

संपादित करें: @ AlexKuznetsov की टिप्पणी ने मेरे प्रश्न को फिर से पढ़ने और मेरे उत्तर में बहुत स्पष्ट त्रुटि को हटाने के लिए प्रेरित किया। देर रात पोस्टिंग पर स्वयं पर ध्यान दें।

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