मर्ज स्टेटमेंट के लिए मेरे लॉकिंग विकल्प क्या हैं?


13

मेरे पास एक संग्रहित प्रक्रिया है जो एक MERGEबयान करती है ।

ऐसा लगता है कि यह मर्ज करते समय डिफ़ॉल्ट रूप से पूरी तालिका को लॉक कर देता है।

मैं इस संग्रहित प्रक्रिया को एक लेनदेन के अंदर बुला रहा हूं जहां मैं कुछ अन्य सामान भी कर रहा हूं और मैं चाहता हूं कि यह केवल प्रभावित पंक्तियों को लॉक करे।

मैंने संकेत की कोशिश की MERGE INTO myTable WITH (READPAST)और यह कम ताला लगा। लेकिन एमएस डॉक में एक चेतावनी थी कि यह प्राथमिक कुंजी को भी दरकिनार करते हुए, डुप्लिकेट कुंजियों को सम्मिलित कर सकता है।

यहाँ मेरा टेबल स्कीमा है:

CREATE TABLE StudentDetails
(
StudentID INTEGER PRIMARY KEY,
StudentName VARCHAR(15)
)
GO
INSERT INTO StudentDetails
VALUES(1,'WANG')
INSERT INTO StudentDetails
VALUES(2,'JOHNSON')
GO

CREATE TABLE StudentTotalMarks
(
Id INT IDENTITY PRIMARY KEY,
StudentID INTEGER REFERENCES StudentDetails,
StudentMarks INTEGER
)
GO
INSERT INTO StudentTotalMarks
VALUES(1,230)
INSERT INTO StudentTotalMarks
VALUES(2,255)
GO

यहाँ मेरी संग्रहीत प्रक्रिया है:

CREATE PROCEDURE MergeTest 
    @StudentId int,
    @Mark int
AS  

WITH Params
AS
(
    SELECT @StudentId as StudentId,
        @Mark as Mark
)
    MERGE StudentTotalMarks AS stm
    USING Params p
    ON stm.StudentID = p.StudentId
    WHEN MATCHED AND stm.StudentMarks > 250 THEN DELETE
    WHEN MATCHED THEN UPDATE SET stm.StudentMarks = p.Mark
    WHEN NOT MATCHED THEN
        INSERT(StudentID,StudentMarks)
        VALUES(p.StudentId, p.Mark);
GO

यहां बताया गया है कि मैं लॉकिंग कैसे देख रहा हूं:

begin tran
EXEC MergeTest 1, 1

और फिर दूसरे सत्र में:

EXEC MergeTest 2, 2

दूसरा सत्र आगे बढ़ने से पहले पहले पूरा होने का इंतजार करता है।


1
WITH (READPAST)SQL सर्वर को केवल उन पंक्तियों को छोड़ देने का निर्देश देता है जो अन्य सत्रों द्वारा लॉक हैं। क्या वाकई आपकी उसे करने की इच्छा है? इसके अलावा, इस तालिका में आप कितनी पंक्तियाँ संशोधित कर रहे हैं? हमें तालिका स्कीमा (अनुक्रमित सहित) और MERGEआपके द्वारा चलाए जा रहे विवरण दिखाएं ।
निक चामास

@NickChammas मदद के लिए धन्यवाद, मैंने विवरण के साथ सवाल अपडेट किया। मुझे लगता है कि READPAST खराब होगा ...
जॉन बुकानन

जवाबों:


12

आपको StudentTotalMarksरिकॉर्ड का पता लगाने के लिए क्वेरी प्रोसेसर को अधिक कुशल एक्सेस पथ देने की आवश्यकता है । जैसा कि लिखा गया है, क्वेरी को [StudentID] = [@StudentId]प्रत्येक पंक्ति पर लागू अवशिष्ट विधेय के साथ तालिका के पूर्ण स्कैन की आवश्यकता होती है :

स्कैन योजना

Uरूपांतरण गतिरोध के एक सामान्य कारण के खिलाफ बुनियादी बचाव के रूप में पढ़ते समय इंजन (अपडेट) लॉक करता है। इस व्यवहार का अर्थ है कि पहले निष्पादन द्वारा Uपहले से ही लॉक X(अनन्य) लॉक वाली पंक्ति पर लॉक प्राप्त करने का प्रयास करते समय दूसरा निष्पादन ब्लॉक ।

निम्न सूचकांक अनावश्यक Uलॉक लेने से बचने के लिए एक बेहतर पहुंच मार्ग प्रदान करता है :

CREATE UNIQUE INDEX uq1 
ON dbo.StudentTotalMarks (StudentID) 
INCLUDE (StudentMarks);

क्वेरी प्लान में अब एक तलाश अभियान शामिल है StudentID = [@StudentId], इसलिए Uकेवल लक्ष्य पंक्तियों पर ताले का अनुरोध किया जाता है:

सीक प्लान

सूचकांक नहीं है की आवश्यकता होने के लिए UNIQUEहाथ में इस मुद्दे को हल करने के लिए (हालांकि INCLUDEयह इस प्रश्न के लिए एक कवर सूचकांक बनाने के लिए आवश्यक है)।

बनाने की मेज भी पहुंच पथ समस्या का समाधान होगा (और जाहिरा तौर पर अनावश्यक स्तंभ हटाया जा सकता है)। आपको हमेशा एक या बाधा के साथ वैकल्पिक कुंजियों को लागू करना चाहिए (और अच्छे कारण के बिना अर्थहीन सरोगेट कुंजियों को जोड़ने से बचना चाहिए)।StudentIDPRIMARY KEYStudentTotalMarksIdUNIQUEPRIMARY KEY

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