SQL सर्वर में, रीड लॉक कैसे काम करते हैं?


17

मान लीजिए कि मेरे पास निम्नलिखित लंबी चलने वाली क्वेरी है

UPDATE [Table1]
SET [Col1] = 'some value'
WHERE [Col2] -- some clause which selects thousands of rows

और मान लें कि उपरोक्त क्वेरी चल रही है, तो निम्नलिखित क्वेरी निष्पादित की गई है

SELECT *
FROM [Table1]

क्या पहली क्वेरी दूसरी क्वेरी को चलने से रोकती है जब तक कि पहली क्वेरी नहीं होती है? यदि ऐसा है, तो पहली क्वेरी दूसरी क्वेरी को सभी पंक्तियों या WHERE क्लॉज में शामिल पंक्तियों पर चलने से रोकती है?

संपादित करें:

मान लीजिए कि दूसरी क्वेरी है

SELECT [Col1], [Col2]
FROM [Table1]
WHERE [Col2] -- some clause whose matching elements overlap those from
             -- the clause in the first query and which has additional matching elements

जवाबों:


14

मैं आपको यह समझने की सलाह देता हूं कि SQL सर्वर किसी क्वेरी को कैसे निष्पादित करता है , यह समझ में आता है कि कैसे काम करता है और कैसे काम करता है और लॉकिंग कैसे काम करता है।

10000ft दृश्य इस प्रकार है:

  • रीड ऑपरेटर्स डेटा को पढ़ने से पहले , उनके द्वारा पढ़े गए डेटा पर साझा ताले प्राप्त करते हैं
  • लिखने वाले ऑपरेटर डेटा को संशोधित करने से पहले संशोधित किए गए डेटा पर अनन्य ताले प्राप्त करते हैं
  • डेटा ताले सिर्फ तार हैं, उदाहरण के लिए। डेटाबेस और ऑब्जेक्ट द्वारा स्कैन की जा रही कुंजी का हैश।
  • लॉक मैनेजर मैट्रिक्स के अनुसार लॉक मैनेजर दी गई सभी तालों की एक सूची रखता है और असंगतताओं का पता लगाता है
  • असंगत अनुरोधों को तब तक निलंबित कर दिया जाता है जब तक कि असंगत अनुदान उन्हें अवरुद्ध नहीं करता है
  • ऑपरेटर उच्च स्तर (पृष्ठ या तालिका स्तर, विभाजन स्तर के विकल्पों की अनदेखी) पर डेटा को पढ़ने या अपडेट करने के इरादे की घोषणा करने के लिए एक लॉक पदानुक्रम का उपयोग करते हैं। यह ऑपरेटरों को प्रत्येक व्यक्तिगत पंक्ति को पूरी तरह से w / o लॉक करने की अनुमति देता है
  • लॉक लाइफटाइम और रेंज लॉक का उपयोग उच्च अलगाव स्तरों को लागू करने के लिए किया जाता है

यह वास्तव में बर्फ बर्ग का सिर्फ टिप है। विषय विशाल है। आपके उदाहरण में, कोई भी आपके सवाल का जवाब नहीं दे सकता है कि वास्तव में क्या बंद किया जा रहा है क्योंकि यह कई कारकों पर निर्भर करेगा। बेशक, कोई भी आवेदन जारी नहीं करना चाहिए SELECT * FROM Table1 क्योंकि यह WHERE क्लॉज गायब है और उपयोग कर रहा है *। ये बुरे व्यवहार हैं क्योंकि, अन्य बातों के अलावा, वे वास्तव में विवाद को बंद कर देंगे।

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


क्या होगा यदि मुझे किसी तालिका की सभी सामग्री चाहिए (कहते हैं कि मेरी इसमें केवल 14 पंक्तियाँ हैं)? SELECT * FROM Table1यदि यह ठीक है कि मुझे क्या चाहिए, तो यह कैसे बुरा है?
अज़ीमुत

1
*अपने आप में एक बुरा अभ्यास है क्योंकि जब टेबल संरचना में परिवर्तन होता है तो आमतौर पर अनुप्रयोग टूट जाता है (अप्रत्याशित कॉलम परिणाम में दिखाई देते हैं)।
रेमस रूसु

3

संपादित करें: जैसा कि @MaxVernon बताते हैं, निम्नलिखित कोई रास्ता नहीं है जो NOLOCK का उपयोग करने का एक सुझाव है , और मुझे बहुत अच्छी तरह से लेन-देन के स्तर को निर्धारित करने का उल्लेख करना चाहिए READ UNCOMMITEDऔर नकारात्मक धारणा NOLOCKको पहले स्थान पर लाने से रोकना चाहिए । तो मूल रूप से पोस्ट किया गया:

त्वरित और सरल है "हाँ, पहली क्वेरी दूसरी क्वेरी को तब तक अवरुद्ध करेगी जब तक कि एक विशिष्ट सूचकांक संकेत निर्दिष्ट नहीं किया जाता है ( NOLOCK , जिसे कभी-कभी" गंदा रीड "कहा जाता है) या दूसरी क्वेरी का लेन-देन अलगाव स्तर READ UNCOMMITED(जो पहचान से संचालित होता है) पर सेट होता है। नहीं, यह नहीं है।"

प्रश्न पर प्रदान किए गए अतिरिक्त विवरण के जवाब में , WITHदूसरे पर एक खंड को शामिल करने के लिए SELECT, पारस्परिक रूप से अनन्य या अन्यथा, दो प्रश्नों के बीच की बातचीत काफी हद तक समान होगी।

IF NOT EXISTS ( SELECT  1
                FROM    sys.objects
                WHERE   name = 'Foo'
                    AND type = 'U' )
BEGIN
    --DROP TABLE dbo.Foo;
    CREATE TABLE dbo.Foo
    (
        Foo_PK          BIGINT IDENTITY( 1, 1 ) NOT NULL,
                            PRIMARY KEY ( Foo_PK ),
        Bar             BIT,
        x               BIT,
        y               BIT,
        z               BIT
    );

    CREATE NONCLUSTERED INDEX IX_Foo_x
        ON  dbo.Foo ( x );

    INSERT INTO dbo.Foo ( Bar, x, y, z )
    VALUES ( 1, 1, 1, 1 ), ( 0, 0, 0, 0 );
END;    
GO

BEGIN TRANSACTION;

UPDATE  dbo.Foo
    SET y = 0
WHERE   x = 1;

-- COMMIT TRANSACTION;

एक अलग सत्र में, निम्नलिखित चलाएँ:

SELECT  *
FROM    dbo.Foo WITH ( NOLOCK );
GO

SELECT  *
FROM    dbo.Foo;

आप वर्तमान में चल रहे ताले की जांच कर सकते हैं sp_lock, अधिमानतः एक और अलग सत्र में:

EXECUTE dbo.sp_lock;

आपको एक KEYप्रकार का लॉक देखना चाहिए जो कि स्पिड ट्रांज़ेक्शन को स्प्रेड द्वारा आयोजित किया जा रहा है X(अनन्य) मोड में, अन्य IX(इंटेंट-एक्सक्लूसिव) लॉक से भ्रमित नहीं होना चाहिए । ताला प्रलेखन इंगित करता है कि, जबकि KEYताला रेंज-विशिष्ट है, यह भी अन्य लेनदेन डालने या डेटा बदलकर प्रभावित स्तंभों को अद्यतन करने से रोकता है उसमें इतना है कि यह मूल प्रश्न के उस सीमा के भीतर गिर सकती है निहित। जैसा कि लॉक ही आयोजित किया जा रहा है, अनन्य है, पहली क्वेरी किसी अन्य समवर्ती लेनदेन से संसाधन तक पहुंच को रोक रही है । वास्तव में, कॉलम की सभी पंक्तियाँ लॉक हैं, चाहे वे पहले क्वेरी द्वारा निर्दिष्ट सीमा के भीतर हों या न हों।

Sताला दूसरे सत्र द्वारा आयोजित किया जा रहा इस प्रकार होगा WAITजब तक Xताला साफ़ करता है, एक और को रोकने Xके लिए (या U) एक अलग समवर्ती spid से उस संसाधन पर पहुंचने से पहले दूसरे सत्र में अपनी पढ़ा आपरेशन पूरा करता है, के अस्तित्व को न्यायोचित ठहरा से ताला Sताला।

अब स्पष्टता के लिए एक संपादित करें: जब तक मैं गलत नहीं हूँ कि एक गंदा पढ़ा यहाँ बताए गए जोखिमों के संक्षिप्त विवरण से क्या है ... संपादित करें 3 : मुझे बस एहसास हुआ कि मैं एक पृष्ठभूमि चौकी के प्रभाव पर विचार नहीं कर रहा हूँ, जो इस प्रकार लिखता है डिस्क पर अभी तक बिना किसी लेनदेन के, हां, मेरा स्पष्टीकरण भ्रामक था।

दूसरी क्वेरी में, पहला बैच (और इस मामले में,) बिना डेटा के वापस आ जाएगा। डिफ़ॉल्ट लेनदेन आइसोलेशन स्तर में चल रहा दूसरा बैच, READ COMMITEDपहले सत्र में कमिट या रोलबैक पूरा होने के बाद ही लौटेगा।

यहां से आप अपनी क्वेरी योजनाओं और संबद्ध लॉक स्तरों को देख सकते हैं, लेकिन बेहतर अभी तक, आप SQL सर्वर के सभी लॉक यहां पढ़ सकते हैं ।


1
उपयोग करने के बारे में चेतावनी का एक शब्द WITH (NOLOCK)इस मामले में मददगार होगा। अधिक पढ़ने के लिए brentozar.com/archive/2011/11/… और brentozar.com/archive/2013/02/… देखें ।
मैक्स वर्नोन

3
ओह, WITH (NOLOCK)स्मृति से गंदे पृष्ठ वापस नहीं आते हैं जो कि प्रतिबद्ध नहीं हैं। यह वास्तव में टेबल से पंक्तियों को पढ़ता है (चाहे डिस्क पर या कैश्ड-इन-मेमोरी) लेखकों को तालिका द्वारा उपयोग की जाने वाली पंक्तियों को अपडेट करने या जोड़ने से अवरुद्ध किए बिना।
मैक्स वर्नोन

2
मैं उलझन में हूं। यदि उत्तर "1 क्वेरी 2 को चलने से रोकती है?" "नहीं" है, दूसरे प्रश्न का उत्तर "हां" कैसे हो सकता है? क्या आप स्पष्ट कर सकते हैं कि आप कौन से प्रश्नों का उत्तर दे रहे हैं, और अपने उत्तरों पर विस्तार करें?
जॉन ऑफ ऑल ट्रेड्स

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