2009-10-06 13 views
29

मैंने यूपलडॉक (like this) के संयोजन में उपयोग किए जाने वाले होल्डॉक संकेत के कई उदाहरण देखे हैं। हालांकि Microsoft's documentation इन संकेतों के लिए ऐसा लगता है कि होल्डॉक को अनावश्यक होना चाहिए, क्योंकि यूपीडॉक पहले ही लेनदेन के अंत तक लॉक बना रहता है। (ऐसा लगता है कि होल्डॉक केवल वैसे भी साझा लॉक पर लागू होता है।)होल्डॉक पर यूपीडॉक पर क्या प्रभाव पड़ता है?

होल्डॉक क्वेरी को कैसे प्रभावित करता है, अगर बिल्कुल?

उत्तर

59

इसका एक बड़ा प्रभाव है।

अद्यतन लॉक पंक्ति पर एक अद्यतन ताला, पृष्ठ पर इरादा अद्यतन और तालिका/डेटाबेस पर साझा लॉक लेता है।

यह तालिका के भीतर डेटा तक पहुंचने से अन्य प्रश्नों को रोकता नहीं है, क्योंकि पेज/डेटाबेस पर ताले पूरी तरह से ताले साझा करते हैं। वे ताले के विपरीत होने वाले ऑपरेशन करने का प्रयास करके व्यक्तिगत पंक्ति/पृष्ठ/तालिका के खिलाफ ताले को तोड़ नहीं सकते हैं। अगर ऐसा हुआ तो अनुरोध वर्तमान ताले के पीछे कतार होगा और आगे बढ़ने से पहले उपलब्ध होने की प्रतीक्षा करेगा।

होल्डॉक का उपयोग करके, क्वेरी को क्रमबद्ध करने के लिए मजबूर किया जा रहा है, जब तक कि कार्रवाई पूरी नहीं हो जाती तब तक तालिका को लॉक कर दें। यह किसी को भी टेबल पढ़ने से रोकता है जब तक कि नोलॉक संकेत का उपयोग नहीं किया जाता है, जिससे संभावित गंदे पढ़ने की अनुमति मिलती है।

प्रभाव देखने के लिए, उदाहरण तालिका 'foo' उत्पन्न करें और इसमें कुछ ट्रैश डेटा डालें।

begin tran 

select * from foo with (updlock) 
where tableid = 1 
-- notice there is no commit tran 

खुला एक और खिड़की और कोशिश:

select * from foo 

पंक्तियों वापस आना, अब मूल प्रश्न लेन-देन के लिए प्रतिबद्ध। पुन: चलाने यह बदल holdlock रूप में अच्छी तरह उपयोग करने के लिए:

begin tran 

select * from foo with (updlock, holdlock) 
where tableid = 1 

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

अंतिम परीक्षण नोलॉक का उपयोग करना है, लेन-देन को फिर से अपडेटॉक और होल्डॉक का उपयोग करना है। तब चलाने दूसरी विंडो में निम्न:

select * from foo (nolock) 

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

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

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

अनुरोध के रूप में संपादित करें: SQL 2005, 2008, 2008R2 (सभी एंटरप्राइज़) में परीक्षण किया गया - सभी बहुत अधिक डिफ़ॉल्ट सेटिंग्स पर स्थापित, सभी डिफ़ॉल्ट का उपयोग करके बनाए गए डेटाबेस का परीक्षण करें (केवल डीबी का नाम दर्ज करें)।

+0

अच्छा उत्तर, धन्यवाद – marijne

+0

अच्छा स्पष्टीकरण, जो बहुत मदद करता है! – Mercurybullet

+0

@ डैरेन - मैंने आपके द्वारा किए गए संपादन को वापस ले लिया है, कोई लॉक डिफ़ॉल्ट नहीं है और दूसरा चयन अपडेट लॉक नहीं लेना चाहिए। – Andrew

12

एंड्रयू जवाब के सही है MSDN प्रलेखीकरण के अनुसार, हालांकि मैं 2008R2 और 2012 के खिलाफ परीक्षण किया है और मैं देख इस व्यवहार तो कृपया अपने आप को

व्यवहार मैं देख रहा हूँ परीक्षण नहीं कर रहा हूँ के रूप में नीचे है:

सबसे पहले इसे प्ले डेटाबेस पर चलाएं।

CREATE TABLE [dbo].[foo](
    [tableid] [int] IDENTITY(1,1) NOT NULL, 
    [Col2] [varchar](100) NOT NULL, 
    CONSTRAINT [PK_foo] PRIMARY KEY CLUSTERED 
    (
     [tableid] ASC 
    ) 
) 

... और डाल में कुछ ऐसी पंक्तियां

अब दो क्वेरी टैब में इस कोड (टैब दो में 'टैब एक' पाठ बदलने) चिपकाएँ:।

begin tran 

select * from foo with (UPDLOCK, HOLDLOCK) 
where tableid = 1 

UPDATE foo SET Col2 = 'tab one' 
where tableid = 1 

commit tran 

और

select * from foo 
where tableid = 1 
    : एक और टैब 3 में रखते
  1. सुनिश्चित करें कि आपके प्ले डेटाबेस पर इशारा करते हुए टेबल कहां है।

  2. हाइलाइट सब कुछटैब 1 और निष्पादित में अद्यतन बयान से पहले।

  3. टैब 2 में एक ही क्या आप टैब 2 होगा पूरा नहीं हुआ है और अभी भी निष्पादित हो रहा है मिल जाएगा।

  4. अब मेरी वातावरण में यह पूरा टैब 3में सरल का चयन करें निष्पादित करें।

  5. हाइलाइट टैब 1 और यह अमल में अद्यतन बयान (नहीं करते अभी तक प्रतिबद्ध), आप टैब 2 अभी भी निष्पादित हो रहा है देखेंगे।

  6. आगे बढ़ो और टैब 1 में प्रतिबद्ध अमल ... टैब 2 अब चयन पूरा हो जाएगा ... आप आराम से चला सकते हैं।

+0

SQL सर्वर का कौन सा संस्करण इस रन के विरुद्ध था? यदि 2012 में व्यवहार बदल सकता है, लेकिन 2005/2008/2008 आर 2 होल्डॉक इसे धारावाहिक मोड में मजबूर करेगा और साझा लॉक लेने से कुछ और अवरुद्ध करेगा - जो 'सरल' चयन जारी करने का प्रयास करेगा। – Andrew

+1

एक अन्य संभावना, आपके पास पंक्ति संस्करण आधारित अलगाव स्विच किया गया है - जब पंक्ति संस्करण आधारित अलगाव जगह पर है, 'सरल' चयन साझा लॉक जारी नहीं करेगा, केवल एक एसएच-एस लॉक - जो इसे अवरुद्ध कर देगा, हालांकि 2008 में अलगाव स्तर डिफ़ॉल्ट नहीं है। परीक्षणों में अंतर की पहचान करना दिलचस्प होगा। – Andrew

+0

@ एंड्रयू और डैरेन: कृपया अपनी संबंधित पोस्ट संपादित करें और नोट करें कि आपके द्वारा SQL सर्वर के कौन से संस्करण * परीक्षण किए गए हैं * आपके समाधान। डिफ़ॉल्ट व्यवहार में किए गए किसी भी बदलाव का वर्णन करने वाले लिंक (या आपके द्वारा बनाई गई किसी भी सेटिंग) की भी सराहना की जाएगी =) –

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

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