"आदेश" नियतात्मक है आपके दृष्टिकोण से केवल तभी जब आप अपनी क्वेरी में ORDER BY शामिल करते हैं। क्या यह नियतात्मक सर्वर के दृष्टिकोण से . है एक कार्यान्वयन विवरण है, जिस पर भरोसा नहीं किया जाना चाहिए।
लॉकिंग के लिए, दो समान डीएमएल स्टेटमेंट एक दूसरे को ब्लॉक (लेकिन डेडलॉक नहीं) कर सकते हैं। उदाहरण के लिए:
CREATE TABLE THE_TABLE (
ID INT PRIMARY KEY
);
लेन-देन ए:
INSERT INTO THE_TABLE VALUES(1);
लेन-देन बी:
INSERT INTO THE_TABLE VALUES(1);
इस समय, लेन-देन B रोका गया . है जब तक लेन-देन ए या तो प्रतिबद्ध नहीं होता या वापस रोल नहीं करता। यदि ए प्रतिबद्ध है, तो प्राथमिक कुंजी उल्लंघन के कारण बी विफल हो जाता है। यदि A पीछे हटता है, तो B सफल होता है।
इसी तरह के उदाहरण UPDATE और DELETE के लिए बनाए जा सकते हैं।
महत्वपूर्ण बिंदु यह है कि अवरोधन निष्पादन योजना पर निर्भर नहीं होगा - कोई फर्क नहीं पड़ता कि Oracle आपकी क्वेरी को कैसे अनुकूलित करता है, आपके पास हमेशा एक ही अवरुद्ध व्यवहार होगा। अधिक जानकारी के लिए आप डीएमएल संचालन में स्वचालित लॉक के बारे में पढ़ना चाह सकते हैं।
जहां तक मृत का प्रश्न है -लॉक, वे कई बयानों के साथ हासिल करना संभव है। उदाहरण के लिए:
A: INSERT INTO THE_TABLE VALUES(1);
B: INSERT INTO THE_TABLE VALUES(2);
A: INSERT INTO THE_TABLE VALUES(2);
B: INSERT INTO THE_TABLE VALUES(1); -- SQL Error: ORA-00060: deadlock detected while waiting for resource
या, संभवतः उन बयानों के साथ जो एक से अधिक पंक्तियों को अलग-अलग क्रम में संशोधित करते हैं और कुछ बहुत ही अशुभ समय (क्या कोई इसकी पुष्टि कर सकता है?)।
--- अद्यतन करें ---
आपके प्रश्न के अद्यतन के जवाब में, मुझे एक सामान्य अवलोकन करने दें:यदि निष्पादन के समवर्ती धागे सुसंगत आदेश में वस्तुओं को लॉक करते हैं , गतिरोध असंभव हैं। यह किसी भी प्रकार के लॉकिंग के लिए सही है, चाहे वह आपके औसत बहु-थ्रेडेड प्रोग्राम में म्यूटेक्स हो (उदाहरण के लिए लॉक पदानुक्रम पर हर्ब सटर के विचार देखें) या यह डेटाबेस हो। एक बार जब आप ऑर्डर को इस तरह बदल देते हैं कि कोई भी दो ताले "फ़्लिप" हो जाते हैं, तो गतिरोध की संभावना शुरू हो जाती है।
अनुक्रमणिका को स्कैन किए बिना, आप अपडेट कर रहे हैं (और लॉक कर रहे हैं ) एक क्रम में पंक्तियाँ, और दूसरे में सूचकांक के साथ। तो, आपके मामले में शायद यही होता है:
- यदि आप दोनों समवर्ती लेनदेन के लिए अनुक्रमणिका स्कैन अक्षम करते हैं , वे दोनों एक ही क्रम में पंक्तियों को लॉक करते हैं [X], इसलिए कोई गतिरोध संभव नहीं है।
- यदि आप केवल एक लेन-देन के लिए अनुक्रमणिका स्कैन सक्षम करते हैं , वे अब उसी क्रम में पंक्तियों को लॉक नहीं करते हैं, इसलिए गतिरोध की संभावना है।
- यदि आप दोनों लेनदेन के लिए अनुक्रमणिका स्कैन सक्षम करते हैं , तो फिर दोनों एक ही क्रम में पंक्तियों को लॉक कर रहे हैं, और एक गतिरोध असंभव है (आगे बढ़ें और
alter session set optimizer_index_cost_adj = 1;
दोनों सत्रों में और आप देखेंगे)।
[X] हालांकि मैं एक गारंटीड ऑर्डर वाले पूर्ण टेबल स्कैन पर भरोसा नहीं करता - यह हो सकता है कि इन विशिष्ट परिस्थितियों में वर्तमान Oracle कैसे काम करता है, और कुछ भविष्य के Oracle या विभिन्न परिस्थितियाँ अलग व्यवहार उत्पन्न कर सकती हैं।
तो, सूचकांक की उपस्थिति आकस्मिक है - असली मुद्दा आदेश दे रहा है। ऐसा ही होता है कि UPDATE में ऑर्डर करना किसी इंडेक्स से प्रभावित हो सकता है, लेकिन अगर हम किसी अन्य तरीके से ऑर्डरिंग को प्रभावित कर सकते हैं, तो हमें समान परिणाम मिलेंगे।
चूंकि UPDATE में ORDER BY नहीं है, आप वास्तव में केवल UPDATE द्वारा लॉकिंग के आदेश की गारंटी नहीं दे सकते। हालांकि, अगर आप अलग अपडेट करने से रोक रहा है, तो आप कर सकते हैं लॉक ऑर्डर की गारंटी दें:
SELECT ... ORDER BY ... FOR UPDATE;
जबकि आपके मूल कोड ने मेरे Oracle 10 वातावरण में गतिरोध पैदा किया, निम्न कोड नहीं करता है:
सत्र 1:
declare
cursor cur is select * from deadlock_test where a > 0 order by a for update;
begin
while true loop
for locked_row in cur loop
update deadlock_test set a = -99999999999999999999 where current of cur;
end loop;
rollback;
end loop;
end;
/
सत्र 2:
alter session set optimizer_index_cost_adj = 1;
declare
cursor cur is select * from deadlock_test where a > 0 order by a for update;
begin
while true loop
for locked_row in cur loop
update deadlock_test set a = -99999999999999999999 where current of cur;
end loop;
rollback;
end loop;
end;
/