2010-07-29 7 views
5

मेरे पास कई .NET प्रक्रियाएं SQL Server 2008 डीबी तालिका से संदेशों को पढ़ने और उन्हें एक समय में संसाधित करने की प्रक्रिया करती हैं। मैं एक ही पंक्ति को संसाधित करने वाली किसी भी दो प्रक्रियाओं से बचने के लिए किसी भी एक प्रक्रिया द्वारा पढ़ी जा रही पंक्ति को 'लॉक' करने के लिए एक सरल एसपी लागू करता हूं।स्पैम निष्पादित करते समय एक पंक्ति को ब्लॉक करें

BEGIN TRAN 

SELECT @status = status FROM t WHERE t.id = @id 
IF @status = 'L' 
BEGIN 
    -- Already locked by another process. Skip this 
    RETURN 0 
END 
ELSE 
    UPDATE t SET status = 'L' WHERE id = @id 
    RETURN 1 
END 

COMMIT 

हालांकि, इस त्रुटिपूर्ण है: कभी कभी एक पंक्ति हो जाता है दो बार के लॉक किए गए 'और प्रसंस्कृत। मुझे संदेह है कि एक सहमति समस्या है: एक अपडेट से पहले स्थिति पढ़ने के दो प्रक्रियाएं।

मुझे लगता है कि किसी भी तरह से एक पठन ब्लॉक को लागू करके इसे हल किया जा सकता है (यानी लेनदेन ब्लॉक पढ़ता है), लेकिन मुझे यह सुनिश्चित नहीं है कि यह कैसे करें। क्या कोई मदद कर सकता है?

SELECT @status = status FROM t (UPDLOCK) WHERE t.id = @id 

अधिक जानकारी के लिए this लिंक को देखें:

अग्रिम धन्यवाद

रयान

+0

मुझे यह जोड़ना चाहिए कि प्रक्रियाएं अलग हैं। नेट प्रक्रियाएं, बहु-थ्रेडेड एकल निष्पादन नहीं, इसलिए इसे सी # प्रोग्रामिंग स्तर पर हल नहीं किया जा सकता है। – Ryan

उत्तर

2

में एक बहुत आप का उपयोग कर प्रयास किया।

बात आप भूल रहे हैं कि एक SELECT बयान सामान्य रूप से, पंक्ति को लॉक नहीं करता इसलिए यदि एक प्रक्रिया SELECT मार डाला है लेकिन अभी तक UPDATE पर अमल नहीं किया गया है, लेकिन फिर किसी अन्य प्रक्रिया साथ आता है और चयन कार्यान्वित , तो यह पंक्ति को वापस करने जा रहा है क्योंकि आपने इसे लॉक नहीं किया है।

UPDLOCK का उपयोग करके, आप उस पंक्ति को अपने चयन कथन के साथ लॉक करते हैं और दूसरी प्रक्रिया को तब तक वापस लेने से रोकते हैं जब तक कि पहली प्रक्रिया लेनदेन को न करे, जो आप चाहते हैं।

संपादित बेशक , एक बयान मार्टिन पता चलता है के रूप में के साथ यह कर सबसे आसान तरीका है और आप सब पर ताला मुद्दे से निपटने के होने से बचने के।

+0

+1 और वास्तव में, अपड्लॉक के साथ आपके वास्तविक लॉकिंग रणनीति को बिना किसी वास्तविक रिकॉर्ड को लॉक करने के लिए समाधान तैयार करना संभव हो सकता है;) – StuartLC

3

क्यों नहीं सिर्फ 2 टेबल से दूर रहेंगे

UPDATE t SET status = 'L' WHERE id = @id and status <> 'L' 
RETURN @@ROWCOUNT 

इस के साथ पूरी बात की जगह तक पहुँचता है और किसी भी आवश्यक से अधिक समय के लिए ताले पकड़े खुला।

+1

मुझे आपका उत्तर बेहतर, बहुत अच्छा लगता है! – dcp

+0

दोह! बेशक। आपका जवाब बहुत ही सुरुचिपूर्ण है, धन्यवाद। हालांकि, मैंने डीसीपी के जवाब को चिह्नित किया क्योंकि मैंने पंक्ति लॉकिंग के बारे में पूछे गए विशिष्ट प्रश्न को संबोधित किया। – Ryan