SQL Server 2005 में डेडलॉक का निदान


82

हम स्टैक ओवरफ्लो SQL सर्वर 2005 डेटाबेस में कुछ खतरनाक, लेकिन दुर्लभ, गतिरोध की स्थिति देख रहे हैं।

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

UPDATE [dbo].[Posts]
SET [AnswerCount] = @p1, [LastActivityDate] = @p2, [LastActivityUserId] = @p3
WHERE [Id] = @p0

अन्य deadlocking बयान बदलता रहता है, लेकिन आमतौर पर तुच्छ, सरल किसी तरह का है पढ़ने पदों तालिका के। यह हमेशा गतिरोध में मारा जाता है। यहाँ एक उदाहरण है

SELECT
[t0].[Id], [t0].[PostTypeId], [t0].[Score], [t0].[Views], [t0].[AnswerCount], 
[t0].[AcceptedAnswerId], [t0].[IsLocked], [t0].[IsLockedEdit], [t0].[ParentId], 
[t0].[CurrentRevisionId], [t0].[FirstRevisionId], [t0].[LockedReason],
[t0].[LastActivityDate], [t0].[LastActivityUserId]
FROM [dbo].[Posts] AS [t0]
WHERE [t0].[ParentId] = @p0

पूरी तरह से स्पष्ट होने के लिए, हम लेखन / गतिरोध नहीं देख रहे हैं, लेकिन पढ़ें / लिखें।

हमारे पास इस समय LINQ का मिश्रण है और SQL क्वेरी को पैरामीटरित किया गया है। हमने with (nolock)सभी एसक्यूएल प्रश्नों को जोड़ा है। इससे कुछ मदद मिली होगी। हमारे पास एक एकल (बहुत) खराब-लिखित बैज क्वेरी थी जिसे मैंने कल तय किया था, जो हर बार चलाने के लिए 20 सेकंड से ऊपर ले जा रहा था, और उसके शीर्ष पर हर मिनट चल रहा था। मैं उम्मीद कर रहा था कि यह लॉकिंग की कुछ समस्याओं का स्रोत था!

दुर्भाग्य से, मुझे लगभग 2 घंटे पहले एक और गतिरोध त्रुटि मिली। समान सटीक लक्षण, वही सटीक अपराधी लिखते हैं।

वास्तव में अजीब बात यह है कि लॉकिंग एसक्यूएल स्टेटमेंट जिसे आप ऊपर देखते हैं, एक बहुत विशिष्ट कोड पथ का हिस्सा है। इसे केवल तब निष्पादित किया जाता है जब किसी प्रश्न में एक नया उत्तर जोड़ा जाता है - यह नई उत्तर गणना और अंतिम तिथि / उपयोगकर्ता के साथ मूल प्रश्न को अद्यतन करता है। यह, जाहिर है, नहीं है कि हम पढ़ रहे हैं की विशाल संख्या के लिए आम रिश्तेदार! जहां तक ​​मैं बता सकता हूं, हम ऐप में कहीं भी बड़ी संख्या में राइट्स नहीं कर रहे हैं।

मुझे पता है कि NOLOCK एक विशालकाय हथौड़े की तरह है, लेकिन हमारे द्वारा यहां चलाए जाने वाले अधिकांश प्रश्नों को सटीक होने की आवश्यकता नहीं है। यदि आपका उपयोगकर्ता प्रोफ़ाइल कुछ सेकंड पुराना है तो क्या आप ध्यान रखेंगे?

Linq के साथ NOLOCK का उपयोग करना थोड़ा अधिक कठिन है क्योंकि स्कॉट हंसेलमैन ने यहां चर्चा की है

हम उपयोग करने के विचार के साथ छेड़खानी कर रहे हैं

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED

आधार डेटाबेस संदर्भ पर ताकि हमारे सभी LINQ प्रश्नों में यह सेट हो। इसके बिना, हम 3-4 लाइन ट्रांजेक्शन कोड ब्लॉक में प्रत्येक लाइनक्यू कॉल जिसे हम बनाते हैं (अच्छी तरह से, सरल रीडिंग वाले, जो कि उनमें से अधिकांश बहुमत है) लपेटना होगा, जो कि बदसूरत है।

मुझे लगता है कि मैं थोड़ा निराश हूं कि SQL 2005 में तुच्छ पढ़ता है लिखने पर गतिरोध कर सकता है। मैं देख सकता हूँ / लिखना गतिरोध एक बहुत बड़ा मुद्दा है, लेकिन पढ़ता है? हम यहां बैंकिंग साइट नहीं चला रहे हैं, हमें हर बार सही सटीकता की आवश्यकता नहीं है।

विचार? विचार?


क्या आप हर ऑपरेशन के लिए SQL DataContext ऑब्जेक्ट के लिए एक नया LINQ इंस्टेंट कर रहे हैं या आप शायद सभी कॉल के लिए एक ही स्थिर संदर्भ साझा कर रहे हैं?

जेरेमी, हम सबसे अधिक भाग के लिए आधार नियंत्रक में एक स्थैतिक डेटाकोटेक्स्ट साझा कर रहे हैं:

private DBContext _db;
/// <summary>
/// Gets the DataContext to be used by a Request's controllers.
/// </summary>
public DBContext DB
{
    get
    {
        if (_db == null)
        {
            _db = new DBContext() { SessionName = GetType().Name };
            //_db.ExecuteCommand("SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED");
        }
        return _db;
    }
}

क्या आप अनुशंसा करते हैं कि हम प्रत्येक नियंत्रक, या प्रति पृष्ठ, या .. के लिए एक नया संदर्भ बनाएं?


2
क्या <a href=" en.wikipedia.org/wiki/... mode</a> आप उपयोग कर, "निराशावादी" (लॉक-आधारित) या "आशावादी" (<a href हैं = " en.wikipedia.org/wiki/ … )?
जॉन सिराकुसा

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

2
वाह - स्कॉट के साथ अपने पॉडकास्ट पर इसके बारे में सुना। विश्वास नहीं कर सकता कि यह बॉक्स से बाहर बेहतर विन्यास के साथ जहाज नहीं करता है, या तो। मैं इसे हमारे डीबीए को दिखा रहा हूँ (क्योंकि वे 'नोलॉक' का बड़े पैमाने पर उपयोग करते हैं)
दान एस्पराजा

3
देखें: इस गतिरोध के कारण के लिए samsaffron.com/archive/2008/08/27/Dlocklocked+ । स्नैपशॉट अलगाव को चालू करना इस समस्या का एक अच्छा समाधान है।
सैम केसर

जवाबों:


44

MSDN के अनुसार:

http://msdn.microsoft.com/en-us/library/ms191242.aspx

जब या तो पढ़े गए SNAPSHOT या ALL SNAPSHOT ISOLATION डेटाबेस विकल्प चालू होते हैं, तो डेटाबेस में किए गए सभी डेटा संशोधनों के लिए तार्किक प्रतियां (संस्करण) बनाए जाते हैं। जब भी किसी पंक्ति को किसी विशिष्ट लेन-देन द्वारा संशोधित किया जाता है, डेटाबेस इंजन का उदाहरण अस्थायी पंक्ति में पंक्ति की पूर्व की प्रतिबद्ध छवि का एक संस्करण संग्रहीत करता है। प्रत्येक संस्करण को लेनदेन के लेनदेन अनुक्रम संख्या के साथ चिह्नित किया जाता है जिसने परिवर्तन किया। एक लिंक सूची का उपयोग करके संशोधित पंक्तियों के संस्करणों को जंजीर बनाया गया है। नवीनतम पंक्ति मान हमेशा वर्तमान डेटाबेस में संग्रहीत किया जाता है और tempdb में संग्रहीत संस्करण पंक्तियों तक जंजीर की जाती है।

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

अतिरिक्त ओवरहेड के लिए मामूली प्रदर्शन दंड प्रतीत होता है, लेकिन यह नगण्य हो सकता है। हमें यह सुनिश्चित करने के लिए परीक्षण करना चाहिए।

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

ALTER Database [StackOverflow.Beta] SET READ_COMMITTED_SNAPSHOT ON

3
"NOLOCKS हमारी डेटा लेयर के साथ मूलभूत मुद्दों को मास्क करेगा" ... NOLOCK मास्क किस तरह की समस्याओं का सामना करता है? अगर मुझे लगता है कि मुझे NOLOCK की आवश्यकता है, तो मुझे किन समस्याओं की तलाश करनी चाहिए?
मैट हैमिल्टन

3
इस उत्तर के बारे में क्या यह "उत्तर" बनाता है? मुझे अभी भी समझ में नहीं आया है कि मिलीसेकंड पढ़ने पर गतिरोध क्यों खत्म हो जाएगा? मैं "user13484" द्वारा जवाब का अनुमान लगा रहा हूं कि अगर मामला है तो इसका कोई संदर्भ नहीं है।
रिचर्ड द किवी

37

NOLOCK और READ UNCOMMITTED एक फिसलन ढलान है। जब तक आपको समझ नहीं आता कि गतिरोध पहले क्यों हो रहा है, तब तक आपको उनका उपयोग नहीं करना चाहिए। मुझे यह चिंता होगी कि आप कहते हैं, "हमने सभी एसक्यूएल प्रश्नों के साथ (नॉल्क) जोड़ा है"। हर जगह NOLOCK के साथ जोड़ने की आवश्यकता एक निश्चित संकेत है कि आपको अपने डेटा स्तर में समस्याएं हैं।

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

इस तरह के डेडलॉक मुद्दे को बहुत काम के बिना और गंदे रीड्स को सक्षम किए बिना प्राप्त करने का एक आसान तरीका है "Snapshot Isolation Mode"(SQL 2005 में नया) का उपयोग करना जो आपको हमेशा पिछले अनमॉडिफाइड डेटा का एक साफ रीड देगा। यदि आप उन्हें इनायत से संभालना चाहते हैं, तो आप बहुत आसानी से डेडलॉक किए गए बयानों को पकड़ सकते हैं और पुनः प्रयास कर सकते हैं।


4
मैं JEzell के साथ हूँ - पहली चीज़ जिस पर मैंने ज़ीरो किया था, वह है 'सेट उत्तर = = निश्चित मूल्य>'। वह मूल्य कहां से आ रहा है? इससे मुझे आश्चर्य होता है कि यदि लेन-देन में कहीं और आप इसे प्राप्त कर चुके हैं तो यह एक तरह से तालों का एक समूह है। मैं उसके साथ शुरू करूँगा। और हाँ, वैश्विक NOLOCK एक बैंड-सहायता है।
कोवन

25

ओपी सवाल यह पूछना था कि यह समस्या क्यों हुई। यह पोस्ट उत्तर देने की उम्मीद करती है कि दूसरों द्वारा काम किए जाने वाले संभावित समाधानों को छोड़ते समय।

यह शायद सूचकांक से जुड़ा मुद्दा है। उदाहरण के लिए, मान लें कि टेबल पोस्ट्स में एक गैर-क्लस्टर इंडेक्स X है जिसमें पेरेंटिड और क्षेत्र का एक (या अधिक) अपडेट किया जा रहा है (AnswerCount, LastActivityDate, LastActivityUserId)।

यदि कोई चयन करें क्लस्टर इंडेक्स पर लॉक करें और इसे अपडेट करने के लिए इंडेक्स एक्स पर राइट-एक्सक्लूसिव लॉक प्राप्त करना होगा।

अब आपके पास एक स्थिति है जहां ए लॉक एक्स है और वाई प्राप्त करने की कोशिश कर रहा है जबकि बी लॉक वाई है और एक्स प्राप्त करने की कोशिश कर रहा है।

बेशक, हमें ओपी को अपनी पोस्टिंग को अपडेट करने के बारे में अधिक जानकारी के साथ अपडेट करने की आवश्यकता होगी कि वास्तव में इसका कारण क्या है, इसकी पुष्टि करने के लिए कौन से इंडेक्स हैं।


मैं इस विश्लेषण से सहमत हूं - SELECT और UPDATE पंक्तियों को एक अलग क्रम में संसाधित कर रहे हैं, इसलिए प्रत्येक एक पंक्ति लॉक प्राप्त करने की कोशिश कर रहे हैं जो दूसरे के पास है।
माइक डिमिक्क

यह इस पूरे धागे की सबसे अच्छी प्रतिक्रिया है और केवल यही व्याख्या करता है कि गतिरोध वास्तव में क्यों होता है। इसका # 1 जवाब बुरा नहीं है क्योंकि यह यहाँ पर सबसे अच्छा है।
जोनाथन केहियास

2 परमाणु सरल कथनों के बीच ताला होने के बारे में कुछ उत्तर याद आ रहे हैं। यह एकमात्र पोस्ट है जो इसे समझाने का प्रयास करती है। हालांकि कथन सरल है, एक टेबल अपडेट में कई CIX और NCIX अपडेट शामिल हो सकते हैं, जो कई ऑपरेशन में फैलता है। NCAD ट्रैवर्सल, CIX बुकमार्क लुकअप में शामिल READ के लिए भी। इसका उसी क्रम में तालिकाओं में शामिल होने आदि से कोई लेना-देना नहीं है (क्या लोग प्रश्न पढ़ते हैं?)
रिचर्डTheKiwi

18

मैं इस प्रश्न और परिचर उत्तर के बारे में बहुत असहज हूँ। वहाँ बहुत कुछ है "इस जादुई धूल की कोशिश करो! वह जादू धूल नहीं!"

मैं कहीं भी नहीं देख सकता कि आपके द्वारा लिए गए ताले को तोड़ दिया गया है, और निर्धारित किया गया है कि सटीक प्रकार के ताले किस गतिरोध में हैं।

आप सभी ने संकेत दिया है कि कुछ ताले होते हैं - न कि गतिरोध।

SQL 2005 में आप इस बारे में अधिक जानकारी प्राप्त कर सकते हैं कि ताले का उपयोग करके क्या किया जा रहा है:

DBCC TRACEON (1222, -1)

ताकि जब गतिरोध हो तो आपको बेहतर निदान मिलेंगे।


13
SQL सर्वर में डेडलॉक मॉनीटर द्वारा एक गतिरोध तुरंत नियंत्रित किया जाता है। DMV एक गतिरोध का निवारण करने के लिए बेकार है क्योंकि पीड़ित का चयन किया जाएगा और इससे पहले कि आप इसे स्पॉट कर सकते हैं, उसे मार दिया जाएगा।
जोनाथन केहियास

14

क्या आप हर ऑपरेशन के लिए SQL DataContext ऑब्जेक्ट के लिए एक नया LINQ इंस्टेंट कर रहे हैं या आप शायद सभी कॉल के लिए एक ही स्थिर संदर्भ साझा कर रहे हैं? मैंने मूल रूप से बाद के दृष्टिकोण की कोशिश की, और जो मुझे याद है, उसने डीबी में अवांछित लॉकिंग का कारण बना। अब मैं हर परमाणु संचालन के लिए एक नया संदर्भ बनाता हूं।


10

घर को जलाने से पहले NOLOCK के साथ एक फ्लाई को पकड़ने के लिए नीचे, आप उस गतिरोध ग्राफ पर एक नज़र डालना चाहते हैं जिसे आपको Profiler के साथ कैप्चर करना चाहिए।

याद रखें कि एक गतिरोध के लिए कम से कम 2 ताले की आवश्यकता होती है। कनेक्शन 1 में लॉक ए है, कनेक्शन 2 के लिए लॉक बी - और इसके विपरीत चाहता है। यह एक बेकार स्थिति है, और किसी को देना होगा।

अब तक आपने जो दिखाया है, वह सरल लॉकिंग द्वारा हल किया गया है, जिसे Sql Server दिन भर करने के लिए खुश है।

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

मुझे उम्मीद है कि इस पहेली को पूरा करने के लिए कम से कम 4 कथन हैं (या एक कथन जो कई ताले लेता है - शायद पोस्ट टेबल पर एक ट्रिगर है?)।


7

यदि आपका उपयोगकर्ता प्रोफ़ाइल कुछ सेकंड पुराना है तो क्या आप ध्यान रखेंगे?

नहींं - यह पूरी तरह से स्वीकार्य है। बेस ट्रांजैक्शन आइसोलेशन लेवल सेट करना शायद जाने का सबसे अच्छा / साफ तरीका है।


5

विशिष्ट रीड / राइट गतिरोध इंडेक्स ऑर्डर एक्सेस से आता है। पढ़ें (T1) सूचकांक A पर पंक्ति का पता लगाता है और फिर सूचकांक B (आमतौर पर क्लस्टर किए गए) पर अनुमानित स्तंभ देखता है। लिखें (T2) इंडेक्स B (क्लस्टर) में बदलाव करता है, तब A पर इंडेक्स A-T1 को S-Lck को अपडेट करना होता है, B पर S-Lck चाहता है, T2 में B पर X-Lck है, A. Dead पर U-Lck चाहता है। , पफ। टी 1 मारा जाता है। यह भारी ओएलटीपी ट्रैफिक वाले वातावरण में प्रचलित है और सिर्फ एक बहुत अधिक इंडेक्स :)। समाधान यह है कि या तो रीड को ए से बी तक नहीं कूदना है (यानी ए में कॉलम शामिल है, या अनुमानित सूची से कॉलम हटाएं) या टी 2 को बी से ए पर कूदने की जरूरत नहीं है (अनुक्रमित कॉलम अपडेट न करें)। दुर्भाग्य से, linq यहाँ आपका दोस्त नहीं है ...


BTW A और B एक ही तालिका के अनुक्रमणिका हैं
रेमस रुसानु

3

@ जेफ़ - मैं निश्चित रूप से इस पर एक विशेषज्ञ नहीं हूं, लेकिन मेरे पास लगभग हर कॉल पर एक नया संदर्भ तुरंत देने के अच्छे परिणाम हैं। मुझे लगता है कि यह एडीओ के साथ हर कॉल पर एक नया कनेक्शन ऑब्जेक्ट बनाने के समान है। ओवरहेड उतना बुरा नहीं है जितना आप सोचते हैं, क्योंकि कनेक्शन पूलिंग अभी भी वैसे भी इस्तेमाल किया जाएगा।

मैं इस तरह एक वैश्विक स्थिर सहायक का उपयोग करता हूं:

public static class AppData
{
    /// <summary>
    /// Gets a new database context
    /// </summary>
    public static CoreDataContext DB
    {
        get
        {
            var dataContext = new CoreDataContext
            {
                DeferredLoadingEnabled = true
            };
            return dataContext;
        }
    }
}

और फिर मैं ऐसा कुछ करता हूं:

var db = AppData.DB;

var results = from p in db.Posts where p.ID = id select p;

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

अद्यतन : फिर से, अपने कोड को देखते हुए, आप केवल उस विशेष नियंत्रक उदाहरण के जीवनकाल के लिए डेटा संदर्भ साझा कर रहे हैं, जो मूल रूप से ठीक लगता है जब तक कि यह किसी भी तरह से नियंत्रक के भीतर म्यूटेंट कॉल द्वारा समवर्ती उपयोग नहीं किया जा रहा हो। विषय पर एक सूत्र में, स्कॉटगू ने कहा:

नियंत्रक केवल एक ही अनुरोध के लिए जीते हैं - इसलिए एक अनुरोध को संसाधित करने के अंत में वे कचरा एकत्र किए जाते हैं (जिसका अर्थ है कि डेटाकोटेक्स्ट एकत्र किया गया है) ...

तो वैसे भी, यह नहीं हो सकता है, लेकिन फिर से यह शायद एक कोशिश के लायक है, शायद कुछ लोड परीक्षण के साथ संयोजन के रूप में।


3

प्र आप भंडारण कर रहे हैं AnswerCountमें Postsपहली जगह में तालिका?

एक वैकल्पिक तरीका है Postsतालिका में "राइट बैक" को समाप्त करके तालिका में संग्रहीत न करके AnswerCountगतिशील रूप से आवश्यक उत्तर की संख्या की गणना करें।

हां, इसका मतलब होगा कि आप एक अतिरिक्त क्वेरी चला रहे हैं:

SELECT COUNT(*) FROM Answers WHERE post_id = @id

या अधिक आम तौर पर (यदि आप होम पेज के लिए इसे प्रदर्शित कर रहे हैं):

SELECT p.post_id, 
     p.<additional post fields>,
     a.AnswerCount
FROM Posts p
    INNER JOIN AnswersCount_view a
    ON <join criteria>
WHERE <home page criteria>

लेकिन यह आम तौर पर परिणाम में होता है INDEX SCANऔर उपयोग करने की तुलना में संसाधनों के उपयोग में अधिक कुशल हो सकता है READ ISOLATION

एक बिल्ली की त्वचा के लिए एक से अधिक तरीके हैं। डेटाबेस स्कीमा का समयपूर्व सामान्यीकरण स्केलेबिलिटी मुद्दों को प्रस्तुत कर सकता है।


3

आप निश्चित रूप से READ_COMMITTED_SNAPSHOT को सेट करना चाहते हैं, जो यह डिफ़ॉल्ट रूप से नहीं है। यह आपको MVCC शब्दार्थ प्रदान करता है। यह वही बात है जो Oracle डिफ़ॉल्ट रूप से उपयोग करता है। MVCC डेटाबेस होना बहुत अविश्वसनीय रूप से उपयोगी है, एक का उपयोग करना पागल नहीं है। यह आपको लेनदेन के अंदर निम्नलिखित चलाने की अनुमति देता है:

अपडेट USERS सेट करें FirstName = 'foobar'; // एक साल के लिए सोने का फैसला।

इस बीच, ऊपर किए बिना, हर कोई ठीक से उस तालिका से चयन करना जारी रख सकता है। यदि आप MVCC से परिचित नहीं हैं, तो आप चौंक जाएंगे कि आप कभी इसके बिना रह पाए थे। गंभीरता से।


3

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

यहां आपको क्या करना चाहिए: गतिरोध की स्थिति का पता लगाने के लिए ट्राइ-कैच (टी-एसक्यूएल में) का उपयोग करें। जब ऐसा होता है, तो क्वेरी को फिर से चलाएँ। यह मानक डेटाबेस प्रोग्रामिंग अभ्यास है।

पॉल नील्सन के एसक्यूएल सर्वर 2005 बाइबिल में इस तकनीक के अच्छे उदाहरण हैं ।

यहां एक त्वरित टेम्प्लेट है जिसका मैं उपयोग करता हूं:

-- Deadlock retry template

declare @lastError int;
declare @numErrors int;

set @numErrors = 0;

LockTimeoutRetry:

begin try;

-- The query goes here

return; -- this is the normal end of the procedure

end try begin catch
    set @lastError=@@error
    if @lastError = 1222 or @lastError = 1205 -- Lock timeout or deadlock
    begin;
        if @numErrors >= 3 -- We hit the retry limit
        begin;
            raiserror('Could not get a lock after 3 attempts', 16, 1);
            return -100;
        end;

        -- Wait and then try the transaction again
        waitfor delay '00:00:00.25';
        set @numErrors = @numErrors + 1;
        goto LockTimeoutRetry;

    end;

    -- Some other error occurred
    declare @errorMessage nvarchar(4000), @errorSeverity int
    select    @errorMessage = error_message(),
            @errorSeverity = error_severity()

    raiserror(@errorMessage, @errorSeverity, 1)

    return -100
end catch;    

2
यह समाधान मुझे क्यों परेशान करता है? !! मैं देख रहा हूँ क्यों वहाँ एक गतिरोध है .. समस्या पर एक बहुत गरीब आदमी की बैंड सहायता नहीं है।
शुद्ध .Krome

2

एक चीज जो मेरे लिए अतीत में काम कर चुकी है, वह सुनिश्चित करती है कि मेरे सभी प्रश्नों और अपडेट संसाधनों (तालिकाओं) को उसी क्रम में अपडेट किया जाए।

यही है, यदि एक क्वेरी टेबल 1, टेबल 2 में अपडेट होती है और एक अलग क्वेरी इसे टेबल 2, टेबल 1 के क्रम में अपडेट करती है, तो आपको गतिरोध दिखाई दे सकता है।

सुनिश्चित नहीं है कि यदि आप LINQ का उपयोग कर रहे हैं तो अपडेट के क्रम को बदलना आपके लिए संभव है। लेकिन यह देखने वाली बात है।


1

यदि आपका उपयोगकर्ता प्रोफ़ाइल कुछ सेकंड पुराना है तो क्या आप ध्यान रखेंगे?

कुछ सेकंड निश्चित रूप से स्वीकार्य होंगे। ऐसा लगता नहीं है कि यह लंबे समय तक, वैसे भी, जब तक कि बड़ी संख्या में लोग एक ही समय में जवाब प्रस्तुत नहीं कर रहे हों।


1

मैं इस पर जेरेमी से सहमत हूं। आप पूछते हैं कि क्या आपको प्रत्येक नियंत्रक या प्रति पृष्ठ के लिए एक नया डेटा संदर्भ बनाना चाहिए - मैं हर स्वतंत्र प्रश्न के लिए एक नया निर्माण करता हूं।

मैं वर्तमान में एक समाधान का निर्माण कर रहा हूं जो आपके जैसे स्थैतिक संदर्भ को लागू करने के लिए इस्तेमाल किया गया था, और जब मैंने तनाव परीक्षण के दौरान एक सर्वर (मिलियन +) के जानवर पर टन के अनुरोधों को फेंक दिया, तो मुझे बेतरतीब ढंग से ताले पढ़ना / लिखना भी मिल रहा था।

जैसे ही मैंने प्रति पंक्ति LINQ स्तर पर एक अलग डेटा संदर्भ का उपयोग करने के लिए अपनी रणनीति बदल दी, और भरोसा किया कि SQL सर्वर अपने कनेक्शन पूलिंग जादू को काम कर सकता है, ताले गायब होने लगे।

बेशक, मैं कुछ समय के दबाव में था, इसलिए एक ही समय में सभी चीजों की कोशिश कर रहा था, इसलिए मैं 100% सुनिश्चित नहीं हो सकता कि यह तय है, लेकिन मेरे पास आत्मविश्वास का एक उच्च स्तर है - चलो इसे इस तरह से रखें ।


1

आपको गंदे रीड्स को लागू करना चाहिए।

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED

यदि आपको अपने प्रश्नों के साथ बिल्कुल सटीक लेन-देन की आवश्यकता नहीं है, तो आपको उच्च संगामिति के साथ तालिकाओं का उपयोग करते समय गंदे रीड्स का उपयोग करना चाहिए। मुझे लगता है कि आपकी पोस्ट टेबल उनमें से एक होगी।

यह आपको तथाकथित "प्रेत रीड्स" दे सकता है, जो तब होता है जब आपकी क्वेरी किसी लेनदेन से डेटा पर काम करती है जो प्रतिबद्ध नहीं हुई है।

हम यहां बैंकिंग साइट नहीं चला रहे हैं, हमें हर बार सही सटीकता की आवश्यकता नहीं है

गंदे रीड्स का इस्तेमाल करें। आप सही हैं कि वे आपको सही सटीकता नहीं देंगे, लेकिन उन्हें आपके मृत लॉकिंग मुद्दों को साफ करना चाहिए।

इसके बिना, हम 3-4 लाइन ट्रांजेक्शन कोड ब्लॉक में, हमारे द्वारा की जाने वाली हर LINQ कॉल (अच्छी तरह से सरल रीडिंग वाले, जो उनमें से अधिकांश हैं) को लपेटना होगा, जो कि बदसूरत है

यदि आप "आधार डेटाबेस संदर्भ" पर गंदे रीड को लागू करते हैं, तो आप हमेशा ट्रांजेक्शनल अखंडता की आवश्यकता होने पर उच्च अलगाव स्तर का उपयोग करके अपने व्यक्तिगत कॉल को लपेट सकते हैं।


1

तो एक रिट्री तंत्र को लागू करने में क्या समस्या है? हमेशा गतिरोध उत्पन्न होने की संभावना रहेगी, इसलिए इसे पहचानने के लिए कुछ तर्क क्यों नहीं हैं और बस फिर से प्रयास करें?

कम से कम कुछ अन्य विकल्प प्रदर्शन पेनल्टी का परिचय नहीं देंगे जो हर समय लिया जाता है जब एक रिट्री सिस्टम शायद ही कभी किक करेगा?

इसके अलावा, जब एक रिट्री होती है तो किसी प्रकार की लॉगिंग को मत भूलना ताकि आप अक्सर दुर्लभ होने की स्थिति में न आएं।


1

अब जब मैं जेरेमी का जवाब देख रहा हूं, मुझे लगता है कि मुझे यह याद रखना याद है कि प्रत्येक डेटा ऑपरेशन के लिए एक नया डेटा कॉन्टेक्स्ट का उपयोग करना सबसे अच्छा अभ्यास है। Rob Conery ने DataContext के बारे में कई पोस्ट लिखे हैं, और वह हमेशा एक सिंगलटन का उपयोग करने के बजाय उन्हें समाचार देता है।

यहाँ हम वीडियो के लिए इस्तेमाल किया गया पैटर्न है। कैसे (कोडप्लेक्स में स्रोत दृश्य के लिए लिंक ):

using System.Configuration;
namespace VideoShow.Data
{
  public class DataContextFactory
  {
    public static VideoShowDataContext DataContext()
    {
        return new VideoShowDataContext(ConfigurationManager.ConnectionStrings["VideoShowConnectionString"].ConnectionString);
    }
    public static VideoShowDataContext DataContext(string connectionString)
    {
        return new VideoShowDataContext(connectionString);
    }
  }
}

फिर सेवा स्तर पर (या अपडेट के लिए और भी दानेदार):

private VideoShowDataContext dataContext = DataContextFactory.DataContext();

public VideoSearchResult GetVideos(int pageSize, int pageNumber, string sortType)
{
  var videos =
  from video in DataContext.Videos
  where video.StatusId == (int)VideoServices.VideoStatus.Complete
  orderby video.DatePublished descending
  select video;
  return GetSearchResult(videos, pageSize, pageNumber);
}

0

मुझे ग्रेग के साथ सहमत होना होगा जब तक कि बिना पढ़े अलगाव स्तर को निर्धारित करने से अन्य प्रश्नों पर कोई बुरा प्रभाव न पड़े।

मुझे यह जानने में दिलचस्पी होगी कि जेफ, इसे डेटाबेस स्तर पर कैसे सेट कर रहा है, यह निम्नलिखित जैसे किसी क्वेरी को प्रभावित करेगा:

Begin Tran
Insert into Table (Columns) Values (Values)
Select Max(ID) From Table
Commit Tran

0

यह मेरे साथ ठीक है अगर मेरी प्रोफ़ाइल डेट से कई मिनट दूर है।

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

यदि "READ UNCOMMITTED" को लागू करना आपकी समस्या को हल नहीं करता है, तो प्रसंस्करण के बारे में बहुत कुछ जानने के बिना मदद करना कठिन है। कुछ अन्य ट्यूनिंग विकल्प हो सकते हैं जो इस व्यवहार में मदद करेंगे। जब तक कुछ MSSQL गुरु बचाव में नहीं आता, मैं विक्रेता को समस्या प्रस्तुत करने की सलाह देता हूं।


0

मैं सब कुछ धुनता रहूंगा; डिस्क सबसिस्टम कैसे प्रदर्शन कर रहे हैं? औसत डिस्क कतार लंबाई क्या है? यदि मैं / O का समर्थन कर रहा हूं, तो असली समस्या ये दो प्रश्न नहीं हो सकते हैं जो गतिरोध हैं, यह एक और प्रश्न हो सकता है जो सिस्टम को टाल रहा है; आपने 20 सेकंड तक एक क्वेरी का उल्लेख किया है जिसे ट्यून किया गया है, क्या अन्य हैं?

लंबे समय से चल रहे प्रश्नों को छोटा करने पर ध्यान दें, मैं शर्त लगाता हूं कि गतिरोध की समस्या गायब हो जाएगी।


0

एक ही समस्या थी, और TransactionScope पर "IsolationLevel = IsolationLevel.ReadUncommitted" का उपयोग नहीं किया जा सकता क्योंकि सर्वर में DTS सक्षम नहीं है (!)।

मैं एक विस्तार विधि के साथ क्या किया था:

public static void SetNoLock(this MyDataContext myDS)
{
    myDS.ExecuteCommand("SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED");
}

इसलिए, महत्वपूर्ण संगामिति तालिकाओं का उपयोग करने वाले चयनों के लिए, हम "nolock" को इस तरह से सक्षम करते हैं:

using (MyDataContext myDS = new MyDataContext())
{
   myDS.SetNoLock();

   //  var query = from ...my dirty querys here...
}

शगुन का स्वागत है!

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