2012-02-29 6 views
13

मेरे पास एक प्रोग्राम है जो ओरेकल डेटाबेस से जुड़ता है और उस पर संचालन करता है। अब मैं उस प्रोग्राम को एसक्यूएल सर्वर डेटाबेस का समर्थन करने के लिए अनुकूलित करना चाहता हूं।SQL सर्वर में, मैं ओरेकल के "अद्यतन WAIT के लिए चयन" के समान एक पंक्ति को कैसे लॉक कर सकता हूं?

Oracle संस्करण में, मैं का उपयोग करें "अद्यतन प्रतीक्षा का चयन करें" विशिष्ट पंक्तियों मैं जरूरत लॉक करने के लिए। मैं उन परिस्थितियों में इसका उपयोग करता हूं जहां अद्यतन SELECT के परिणाम पर आधारित होता है और अन्य सत्र पूरी तरह से इसे संशोधित नहीं कर सकते हैं, इसलिए उन्हें इसे मैन्युअल रूप से लॉक करना होगा। सिस्टम एक ही समय में एक ही डेटा तक पहुंचने की कोशिश कर रहे सत्रों के अधीन है।

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

BEGIN TRANSACTION; 
SELECT ITEM_ID FROM TABLE_ITEM WHERE ITEM_PRIORITY > 10 AND ITEM_CATEGORY = 'CT1' 
    ITEM_STATUS = 'available' AND ROWNUM = 1 FOR UPDATE WAIT 5; 
UPDATE [locked item_id] SET ITEM_STATUS = 'unavailable'; 
COMMIT TRANSACTION; 

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

तो आखिरकार, सवाल यह है कि मैं SQL सर्वर में एक ही परिणाम कैसे प्राप्त करूं? मैं संकेतों को लॉक करने पर विचार कर रहा हूं, सिद्धांत रूप में, ऐसा लगता है कि उन्हें काम करना चाहिए। हालांकि, केवल ताले जो अन्य ताले को रोकते हैं "अपडॉक" और "एक्सलॉक" हैं जो दोनों केवल टेबल स्तर पर काम करते हैं।
उन पर ताला लगा संकेत है कि एक पंक्ति स्तर पर काम करने के सभी साझा ताले, जो भी मेरी जरूरतों को संतुष्ट नहीं है (दोनों उपयोगकर्ताओं को एक ही समय में एक ही पंक्ति लॉक कर सकता है, दोनों के रूप में उपलब्ध नहीं चिह्नित करने और इसी मद पर अनावश्यक कार्रवाई कर रहे हैं)।

कुछ लोग "समय संशोधित" कॉलम जोड़ते हैं, इसलिए सत्र यह सत्यापित कर सकते हैं कि वे इसे संशोधित कर चुके हैं, लेकिन ऐसा लगता है कि बहुत सारी अनावश्यक और अनावश्यक पहुंच होगी।

उत्तर

7

एसक्यूएल सर्वर में ताला लगा संकेत देखते हैं, लेकिन वे Oracle उदाहरण आपके द्वारा दी गई की तरह उनके बयान अवधि नहीं है। SQL सर्वर में ऐसा करने का तरीका लेनदेन पर एक अलगाव स्तर सेट करना है जिसमें वह कथन शामिल है जिन्हें आप निष्पादित करना चाहते हैं। this MSDN page देखें लेकिन सामान्य संरचना कुछ ऐसा दिखाई देगा:

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; 

BEGIN TRANSACTION; 

    select * from ... 

    update ... 

COMMIT TRANSACTION; 

serializable उच्चतम अलगाव स्तर है। अन्य विकल्पों के लिए लिंक देखें। MSDN से:

serializable निम्नलिखित निर्दिष्ट करता है:

वक्तव्य डेटा है कि संशोधित किया गया है नहीं पढ़ सकते हैं लेकिन अन्य लेनदेन द्वारा प्रतिबद्ध अभी तक नहीं।

कोई अन्य लेनदेन डेटा कि वर्तमान लेन-देन से पढ़ा जा चुका है जब तक कि वर्तमान लेन-देन पूर्ण संशोधित कर सकते हैं।

अन्य लेनदेन कुंजी मान के साथ नए पंक्तियाँ नहीं डाल सकते कि होगा वर्तमान लेन-देन में कोई बयान द्वारा पढ़ा जब तक वर्तमान लेन-देन पूर्ण कुंजी की सीमा में गिरावट।

+3

यह जानना अच्छा है, लेकिन ऐसा लगता है कि Serializable पढ़ता ही अगर डेटा संशोधित किया गया है नहीं कर पाएगा, तो यह है कि क्षण तक ताले नहीं रोकेगा। – Paradoxyde

+0

@ पैराडाक्सीडे: यह मेरी समझ नहीं है। Spec के दूसरे आइटम के अनुसार (उपरोक्त मेरा संपादन देखें) जैसे ही लेनदेन के अंत तक इसे पढ़ा जाता है, पंक्ति को लॉक कर दिया जाता है। क्या आप इस सवाल का हिस्सा प्राप्त कर रहे हैं? –

+4

यह एक साझा लॉक और बाद में एक विशेष लॉक प्राप्त करता है, इसलिए यह डेडलॉक्स – Andomar

1

क्या आपने (ROWLOCK) के साथ प्रयास किया है?

BEGIN TRAN 

    UPDATE your_table WITH (ROWLOCK) 
    SET your_field = a_value 
    WHERE <a predicate> 

COMMIT TRAN 
+1

ROWLOCK दो उपयोगकर्ताओं को एक ही पंक्ति को संशोधित करने से रोकता है, लेकिन यह दो उपयोगकर्ताओं को उसी पंक्ति को लॉक करने से रोकता नहीं है। – Paradoxyde

+0

मैं देखता हूं, स्पष्टीकरण के लिए धन्यवाद। – Pablushka

+0

@ पैराडाक्सीडे यदि दो लोग एक ही पंक्ति को लॉक करते हैं, तो यह एक डेडलॉक होगा। क्या पंक्ति अपडेट सफल होगा? –

9

शायद आप with (updlock, holdlock) देख रहे हैं। यह select को exclusive लॉक ले जाएगा, जो shared लॉक के बजाय अपडेट के लिए आवश्यक है। holdlock संकेत लेनदेन समाप्त होने तक लॉक रखने के लिए SQL सर्वर को बताता है।

FROM TABLE_ITEM with (updlock, holdlock) 
+0

मैं मानता हूं कि यह लॉक का प्रकार है जिसे मैं ढूंढ रहा हूं, हालांकि, जैसा कि मैंने सवाल में कहा है, अपडेटलॉक पूरी तालिका को प्रभावित करता है, जबकि मैं केवल एक पंक्ति को प्रभावित करना चाहता हूं। – Paradoxyde

+3

'updlock' लॉक के प्रकार को बदलता है (अनन्य बनाम साझा) लेकिन लॉक नहीं है। संपूर्ण तालिका को लॉक करने के लिए, '(tablock) 'के साथ निर्दिष्ट करें, या पंक्ति को लॉक करने के लिए,' (rowlock) के साथ निर्दिष्ट करें' – Andomar

1

documentation के रूप में सईद:

XLOCK

निर्दिष्ट करता है कि अनन्य ताले लिया और आयोजित होने वाले जब तक लेन-देन पूर्ण कर रहे हैं। यदि ROWLOCK, PAGLOCK, या TABLOCK, के साथ निर्दिष्ट किया गया है तो अनन्य ताले ग्रैन्युलरिटी के उचित स्तर पर लागू होते हैं।

तो समाधान WITH(XLOCK, ROWLOCK) उपयोग कर रहा है:

BEGIN TRANSACTION; 

SELECT ITEM_ID 
FROM TABLE_ITEM 
WITH(XLOCK, ROWLOCK) 
WHERE ITEM_PRIORITY > 10 AND ITEM_CATEGORY = 'CT1' AND ITEM_STATUS = 'available' AND ROWNUM = 1; 

UPDATE [locked item_id] SET ITEM_STATUS = 'unavailable'; 

COMMIT TRANSACTION; 
संबंधित मुद्दे

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