XLOCK के साथ SELECT… का उपयोग करने के अच्छे कारण हैं?


11

मैं कुछ फिर से होने वाले गतिरोधों का सामना कर रहा हूं, जिनमें से एक कीलॉक है और इसमें XLOCK संकेत के साथ एक चयन क्वेरी है जो गतिरोध का शिकार बन जाता है। अन्य कथन एक तालिका में एक INSERT है जो पहली क्वेरी के दृश्य का हिस्सा है।

राय:

create view dbo.viewE
 as
    select * from dbo.E  
    where myValue > 13000 

क्वेरी का चयन करें:

select * from dbo.viewE with (XLOCK) where A > GETUTCDATE() 

INSERT कथन:

INSERT INTO [dbo].[E] (myValue,A) VALUES (10,GetDate())

अंतर्निहित तालिका dbo.E लगभग 20 स्तंभों में लगभग 3 मिलियन पंक्तियों को पकड़े हुए है, उनमें से कुछ नेक्स्ट हैं।

प्रश्नों को बाहर ले जाना और दो लेनदेन के साथ मैन्युअल रूप से अनुकरण करना, व्यवहार फिर से उत्पादक है। यदि XLOCK को चयन से हटा दिया जाता है तो व्यवहार बदल जाता है।

गतिरोध ग्राफ:

<deadlock-list>
 <deadlock victim="process222222221">
  <process-list>
   <process id="process222222221" taskpriority="0" logused="0" waitresource="KEY: 5:72057604035644444 (ccdf51accc0c)" waittime="2522" ownerId="27202256401" transactionname="SELECT" lasttranstarted="2015-09-14T16:32:36.160" XDES="0x2f1ec5ca0" lockMode="RangeX-X" schedulerid="15" kpid="12936" status="suspended" spid="359" sbid="0" ecid="0" priority="0" trancount="0" lastbatchstarted="2015-09-14T16:32:36.160" lastbatchcompleted="2015-09-14T16:32:36.160" clientapp="x" hostname="x" hostpid="14536" loginname="x" isolationlevel="serializable (4)" xactid="27202256401" currentdb="5" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
    <executionStack>
     <frame procname="adhoc" line="1" stmtstart="48" sqlhandle="0x02000000611e4523142b2318c47c87313a9b2ba587ff3130">
        SELECT * FROM viewE WITH (XLOCK) WHERE A &lt; GetUtcDate()      </frame>
     <frame procname="unknown" line="1" sqlhandle="0x000000000000000000000000000000000000000000000000">
unknown     </frame>
    </executionStack>
    <inputbuf>
(@UICulture nvarchar(5))SELECT * FROM viewE WITH (XLOCK) WHERE A &lt; GetUtcDate()    </inputbuf>
   </process>
   <process id="process6022222" taskpriority="0" logused="161152" waitresource="KEY: 5:72057604035644444 (cd874c2ba438)" waittime="1370" ownerId="27202248438" transactionguid="0x8de5ccd6eeef67469c6234af59e44ca5" transactionname="DTCXact" lasttranstarted="2015-09-14T16:32:34.767" XDES="0x4aa0bf950" lockMode="RangeI-N" schedulerid="14" kpid="6636" status="suspended" spid="329" sbid="0" ecid="0" priority="0" trancount="2" lastbatchstarted="2015-09-14T16:32:37.300" lastbatchcompleted="2015-09-14T16:32:37.300" clientapp="x" hostname="x" hostpid="14536" loginname="x" isolationlevel="read uncommitted (1)" xactid="27202248438" currentdb="5" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
    <executionStack>
     <frame procname="adhoc" line="1" stmtstart="936" sqlhandle="0x020000004853462f09790a4ddedc0d574c2afa539aef1c0e">
     INSERT INTO [E] ([a], [b], [c],...) VALUES (@aDate, @bDate, @c, ...)
     </frame>
     <frame procname="unknown" line="1" sqlhandle="0x000000000000000000000000000000000000000000000000">
unknown     </frame>
    </executionStack>
    <inputbuf>INSERT INTO [E] ([a], [b], [c],...) VALUES (@aDate, @bDate, @c, ...)
    </inputbuf>
   </process>
  </process-list>
  <resource-list>
   <keylock hobtid="72057604035644444" dbid="5" objectname="db.dbo.E" indexname="IX_index1" id="lock258b6dc80" mode="X" associatedObjectId="72057604035644444">
    <owner-list>
     <owner id="process6022222" mode="X"/>
    </owner-list>
    <waiter-list>
     <waiter id="process222222221" mode="RangeX-X" requestType="wait"/>
    </waiter-list>
   </keylock>
   <keylock hobtid="72057604035644444" dbid="5" objectname="db.dbo.E" indexname="IX_index1" id="lock7b145c400" mode="RangeX-X" associatedObjectId="72057604035644444">
    <owner-list>
     <owner id="process222222221" mode="RangeX-X"/>
    </owner-list>
    <waiter-list>
     <waiter id="process6022222" mode="RangeI-N" requestType="wait"/>
    </waiter-list>
   </keylock>
  </resource-list>
 </deadlock>
</deadlock-list>

जहां तक ​​मैं यह समझता हूं, मैं एक KEYLOCK गतिरोध को देख रहा हूं जो मूल रूप से एक खुला सूचकांक सूचकांक के कारण होता है जो आवश्यक मानों को इकट्ठा करने के लिए एक गैर-संकुलित और संकुल सूचकांक का उपयोग करता है, है ना?

मेरे सवाल:

  1. आवश्यक NTEXT कॉलम शामिल होने के कारण मैं एक कवरिंग इंडेक्स नहीं बना सकता। क्या यहां पंक्तियों की संख्या में भारी कमी करने से मदद मिलेगी?
  2. क्या कोई अच्छा कारण है जो मुझे नहीं पता कि SELECT को XLOCK के साथ निष्पादित किया गया है? क्या एक्सलेक के बिना भी गतिरोध होगा?

जवाबों:


15

जहां तक ​​मैं यह समझता हूं, मैं एक KEYLOCK गतिरोध को देख रहा हूं जो मूल रूप से एक खुला सूचकांक सूचकांक के कारण होता है जो आवश्यक मानों को इकट्ठा करने के लिए एक गैर-संकुलित और संकुल सूचकांक का उपयोग करता है, है ना?

अनिवार्य रूप से, हाँ। रीड ऑपरेशन (चयन) पहले गैर-अनुक्रमित सूचकांक तक पहुंचता है, फिर क्लस्टर इंडेक्स (लुकअप)। लेखन ऑपरेशन (सम्मिलित करें) पहले संकुल सूचकांक तक पहुँचता है, फिर गैर-अनुक्रमित सूचकांक। असंगत ताले को पकड़े हुए एक अलग क्रम में समान संसाधनों तक पहुंचने से गतिरोध पैदा हो सकता है।

क्या यहां पंक्तियों की संख्या में भारी कमी करने से मदद मिलेगी?

यह हो सकता है , क्योंकि कम संसाधन बंद हैं और ऑपरेशन अधिक तेज़ी से पूरा होगा। यदि यह मदद करता है, तो यह गतिरोध को कम कर सकता है , लेकिन सबसे अधिक संभावना है कि उन्हें समाप्त न करें (लेकिन पढ़ें)।

क्या कोई अच्छा कारण है जो मुझे नहीं पता कि SELECT को XLOCK के साथ निष्पादित किया गया है?

ज़रुरी नहीं। इस तरह के लॉकिंग संकेत अक्सर लोगों द्वारा पूरी तरह से समझाए जाते हैं कि किसी समस्या को कम करने या खत्म करने के लिए एक अलग प्रयास में अलगाव, लॉकिंग और गतिरोध कैसे काम करते हैं।

क्या एक्सलेक के बिना भी गतिरोध होगा?

नहीं , यदि चयन वास्तव में बिना पढ़े हुए अलगाव पर चलता है क्योंकि असंगत ताले को एक अलग क्रम में नहीं लिया जाएगा (और आयोजित किया जाता है)।

हां , यदि एक लॉकिंग आइसोलेशन स्तर का उपयोग किया जाता है, और असंगत ताले को असंगत क्रम में लिया और आयोजित किया जाता है, उदाहरण के लिए, नॉनक्लेस्टेड पर साझा (एस), तो पढ़ते समय क्लस्टर पर एस। इस परिदृश्य में गतिरोध कितना संभावित है, इस बात पर निर्भर करता है कि कितने ताले लगे हैं, और कितने समय के लिए आयोजित किए गए हैं।

सलाह

वास्तव में जो बात सामने आती है (समीक्षा करने पर) वह यह है कि चयनित लेनदेन क्रमिक अलगाव के तहत चल रहा है । यह आपके ढांचे द्वारा, या DTC (डिस्ट्रिब्यूटेड ट्रांजैक्शन कोऑर्डिनेटर) के उपयोग के कारण सेट किया जा सकता है - डेडलॉक ग्राफ में लेनदेननाम = "DTCXact" देखें। आपको इसके कारणों पर गौर करना चाहिए, और यदि संभव हो तो इसे बदलने के लिए देखना चाहिए।

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

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

अंत में, XLOCKसंकेत है प्रतिकूल है, लेकिन क्या तुम सच में serializable अलगाव स्तर के उपयोग के लिए कारण पर गौर करने की जरूरत है। यह trancount = 2भी दिलचस्प है - शायद आप अनजाने में यहां लेनदेन कर रहे हैं। जाँच करने के लिए कुछ और।


2
  1. तेजी से पंक्तियों की संख्या कम करने से गतिरोध होने की संभावना कम हो जाएगी, लेकिन यह पूरी तरह से दूर नहीं जाएगी।

सरल शब्दों में चयन पहले पंक्तियों का चयन करने के लिए सूचकांक का उपयोग करना है, फिर पंक्तियों को लाना है, जबकि सम्मिलित पंक्ति को सम्मिलित कर रहा है, फिर (XLOCKED) सूचकांक को अपडेट करने की कोशिश कर रहा है।

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

यह कहने के बाद, XLOCK को हटाने से समस्या का समाधान नहीं होगा। चयन अभी भी सूचकांक पर एक साझा ताला निकाल लेगा, और INSERT इसे अपडेट करने के लिए XLOCK चाहेगा। एक साझा लॉक और एक XLOCK ऑब्जेक्ट पर एक साथ मौजूद नहीं हो सकता है, इसलिए आपको अभी भी एक गतिरोध मिलेगा। IX_Index1 MyValue या A, या दोनों होना चाहिए।

इस प्रकार का गतिरोध अक्सर खराब डिज़ाइन किए गए इंडेक्स और / या बहुत अधिक इंडेक्स के कारण होता है। या खराब लिखा हुआ कोड। आपका सबसे अच्छा विकल्प यह देखना है कि किसी अन्य इंडेक्स का उपयोग करने के लिए चयन को फिर से लिखा जा सकता है या नहीं।

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