रो लॉक कंटेंट को ट्रेस करना, डिबग करना और उसे ठीक करना


12

देर से, मैं बहुत से पंक्ति अवरोधों का सामना कर रहा हूं। विवाद की तालिका एक विशेष तालिका प्रतीत होती है।

यह आमतौर पर होता है -

  • डेवलपर 1 ओरेकल फॉर्म्स फ्रंट एंड स्क्रीन से लेनदेन शुरू करता है
  • डेवलपर 2 एक ही स्क्रीन का उपयोग करके एक अलग सत्र से एक और लेनदेन शुरू करता है

~ 5 मिनट में, सामने का छोर अनुत्तरदायी लगता है। जाँच सत्र पंक्ति लॉक विवाद को दर्शाता है। "समाधान" जिसे हर कोई फेंकता है सत्रों को मारने के लिए है: /

डेटाबेस डेवलपर के रूप में

  • पंक्ति लॉक सामग्री को समाप्त करने के लिए क्या किया जा सकता है?
  • क्या यह पता लगाना संभव होगा कि किसी संग्रहीत कार्यविधि की कौन सी पंक्ति इन पंक्ति अवरोधों का कारण बन रही है
  • ऐसी समस्याओं को कम करने / टालने / दूर करने के लिए सामान्य दिशानिर्देश क्या होगा जो कोडिंग करते हैं?

यदि यह प्रश्न बहुत खुली-खुली / अपर्याप्त जानकारी महसूस करता है, तो कृपया बेझिझक संपादित करें / मुझे बताएं - मैं कुछ अतिरिक्त जानकारी जोड़ने की पूरी कोशिश करूंगा।


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


डेटाबेस संस्करण Oracle डेटाबेस 10g एंटरप्राइज़ संस्करण रिलीज़ 10.2.0.1.0 - 64 बिट है। तर्क के प्रवाह को दोनों सत्रों में एक ही क्रम निष्पादित किया जाता है, लेन-देन को बहुत लंबे समय तक खुला नहीं रखा जाता है (या कम से कम मुझे ऐसा लगता है), और लेनदेन के सक्रिय निष्पादन के दौरान ताले होते हैं।


अद्यतन: तालिका पंक्ति गणना मेरी अपेक्षा लगभग ३.१ मिलियन पंक्तियों से बड़ी है। इसके अलावा, मैंने एक सत्र को ट्रेस करने के बाद पाया कि इस तालिका में कुछ अपडेट स्टेटमेंट्स इंडेक्स का उपयोग नहीं कर रहे हैं। ऐसा क्यों है - मुझे यकीन नहीं है उस खंड में संदर्भित कॉलम जहां खंड को अनुक्रमित किया गया है। मैं वर्तमान में सूचकांक का पुनर्निर्माण कर रहा हूं।


1
@ सत्य - क्या आप संग्रहीत प्रक्रिया की जटिलता को विस्तृत कर सकते हैं? संदिग्ध तालिका कठोर अद्यतन या सम्मिलित करने के तहत है?
कोडरहॉक

क्या विदेशी कुंजियाँ यहाँ एक भूमिका निभाती हैं? (कभी-कभी इसमें सूचकांक की आवश्यकता होती है) डेटाबेस का कौन सा संस्करण है? क्या दोनों सत्रों में तर्क के प्रवाह को एक ही क्रम में निष्पादित किया जाता है? क्या लेन-देन लंबे समय तक 'खुला' रखा जाता है? क्या उपयोगकर्ताओं को समय लगता है या लेनदेन के सक्रिय निष्पादन के दौरान लॉक होता है?
ik_zelf

@ कैंडी ने मैंने सवाल अपडेट किया है
सत्यजित भट्ट

@ik_zelf मैंने सवाल अपडेट किया है
सत्यजित भट

1
यह मेरे लिए स्पष्ट नहीं है कि यह एक समस्या क्यों है - ओरेकल ठीक वही कर रहा है जो इसे करना चाहिए, जो एकल पंक्ति तक पहुंच को क्रमबद्ध कर रहा है। यदि किसी के पास वह पंक्ति है, तो आप इसके पिछले संस्करण को पढ़ सकते हैं, लेकिन लिखने के लिए आपको ताला जारी करने के लिए उनका इंतजार करना होगा। इसके लिए एकमात्र "फिक्स" या तो एक है) चारों ओर मूर्ख नहीं और COMMITया ROLLBACKएक उचित समय में या बी) ऐसी व्यवस्था करें कि वही लोग हमेशा एक ही समय में एक ही पंक्ति नहीं चाहते हैं।
गयुस

जवाबों:


10

क्या यह पता लगाना संभव होगा कि किसी संग्रहीत प्रक्रिया की कौन सी पंक्ति इन पंक्ति अवरोधों का कारण बन रही है?

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

SELECT sid, sql_text
FROM v$session s
LEFT JOIN v$sql q ON q.sql_id=s.sql_id
WHERE state = 'WAITING' AND wait_class != 'Idle'
AND event = 'enq: TX - row lock contention';

कोडिंग के साथ ऐसी समस्याओं को कम करने / टालने / समाप्त करने के लिए सामान्य दिशानिर्देश क्या होगा?

ताले पर ओरेकल अवधारणाओं गाइड अनुभाग कहते हैं, "एक पंक्ति लॉक किया गया है केवल जब एक लेखक के द्वारा संशोधित किया।" एक ही पंक्ति को अपडेट करने वाला एक और सत्र तब पहले सत्र के लिए COMMITया ROLLBACKइसके आगे जारी रहने तक प्रतीक्षा करेगा । समस्या को समाप्त करने के लिए आप उपयोगकर्ताओं को अनुक्रमित कर सकते हैं, लेकिन यहाँ कुछ चीजें हैं जो समस्या को कम कर सकती हैं शायद यह एक मुद्दा नहीं है।

  • COMMITअधिक बार। प्रत्येक COMMITरिलीज़ लॉक होता है, इसलिए यदि आप बैचों में अपडेट कर सकते हैं, तो एक ही पंक्ति की आवश्यकता वाले दूसरे सत्र की संभावना कम हो जाती है।
  • सुनिश्चित करें कि आप उनके मानों को बदले बिना किसी भी पंक्तियों को अपडेट नहीं कर रहे हैं। उदाहरण के लिए, UPDATE t1 SET f1=DECODE(f2,’a’,f1+1,f1);अधिक चयनात्मक (कम ताले पढ़ें) के रूप में फिर से लिखा जाना चाहिए UPDATE t1 SET f1=f1+1 WHERE f2=’a’;। बेशक अगर बदलते बयान अभी भी मेज पर पंक्तियों के बहुमत को लॉक करेंगे तो परिवर्तन को केवल पठनीयता का लाभ होगा।
  • सुनिश्चित करें कि आप उच्चतम वर्तमान मान में एक जोड़ने के लिए तालिका को लॉक करने के बजाय अनुक्रम का उपयोग कर रहे हैं।
  • सुनिश्चित करें कि आप एक फ़ंक्शन का उपयोग नहीं कर रहे हैं जो एक सूचकांक का उपयोग नहीं कर रहा है। यदि फ़ंक्शन आवश्यक है, तो इसे फ़ंक्शन आधारित इंडेक्स बनाने पर विचार करें।
  • सेट में सोचो। इस बात पर विचार करें कि क्या पीएल / एसक्यूएल अपडेट्स के ब्लॉक को चलाने वाला एक लूप को एकल अपडेट स्टेटमेंट के रूप में फिर से लिखा जा सकता है। यदि नहीं तो शायद थोक प्रसंस्करण के साथ प्रयोग किया जा सकता है BULK COLLECT ... FORALL
  • जो काम पहले UPDATEऔर बीच में हो जाए उसे कम करें COMMIT। उदाहरण के लिए, यदि कोड प्रत्येक अद्यतन के बाद एक ईमेल भेजता है, तो ईमेल को कतारबद्ध करने और अपडेट करने के बाद उन्हें भेजने पर विचार करें।
  • SELECT ... FOR UPDATE NOWAITया करने के लिए प्रतीक्षा से निपटने के लिए एप्लिकेशन डिज़ाइन करें WAIT 2। फिर आप पंक्ति को लॉक करने में असमर्थता को पकड़ सकते हैं और उपयोगकर्ता को सूचित कर सकते हैं कि एक और सत्र उसी डेटा को संशोधित कर रहा है।

7

मैं एक डेवलपर दृष्टिकोण से उत्तर प्रदान करूंगा।

मेरी राय में, जब आप एक पंक्ति विवाद का सामना करते हैं, जैसे कि आप जो वर्णन करते हैं, वह इसलिए है क्योंकि आपके आवेदन में एक बग है। ज्यादातर मामलों में इस प्रकार का विवाद एक खो-खो जोखिम का संकेत है। AskTom पर यह थ्रेड एक खोए हुए अद्यतन की अवधारणा को बताता है:

एक खोया अद्यतन तब होता है:

सत्र 1: टॉम के कर्मचारी रिकॉर्ड को पढ़ें

सत्र 2: टॉम का कर्मचारी रिकॉर्ड पढ़ें

सत्र 1: टॉम के कर्मचारी रिकॉर्ड को अपडेट करें

सत्र 2: टॉम के कर्मचारी रिकॉर्ड को अपडेट करें

सत्र 2 कभी भी बिना देखे ही सत्र 1 के परिवर्तन को छोड़ देगा - जिसके परिणामस्वरूप एक अद्यतन खो जाएगा।

आपने खोए हुए अद्यतन का एक बुरा पक्ष-प्रभाव अनुभव किया है: सत्र 2 को अवरुद्ध किया जा सकता है क्योंकि सत्र 1 अभी तक शुरू नहीं हुआ है। हालांकि मुख्य समस्या यह है कि सत्र 2 नेत्रहीन रिकॉर्ड को अपडेट करता है। मान लीजिए कि दोनों सत्र बयान जारी करते हैं:

UPDATE table SET col1=:col1, ..., coln=:coln WHERE id = :pk

दोनों बयानों के बाद, सत्र 1 के संशोधनों को अधिरोपित किया गया है, बिना सत्र 2 को सूचित किया गया है कि पंक्ति को सत्र 1 द्वारा संशोधित किया गया था।


खोया हुआ अपडेट (और विवाद पक्ष प्रभाव) कभी भी नहीं होना चाहिए, वे 100% परिहार्य हैं। आपको उन्हें दो मुख्य तरीकों से रोकने के लिए लॉकिंग का उपयोग करना चाहिए: आशावादी और निराशावादी लॉकिंग

1) निराशावादी लॉकिंग

आप एक पंक्ति को अद्यतन करना चाहते हैं। इस मोड में आप दूसरों को उस पंक्ति ( SELECT ... FOR UPDATE NOWAITस्टेटमेंट) पर लॉक का अनुरोध करके इस पंक्ति को संशोधित करने से रोकेंगे । यदि पंक्ति पहले से ही संशोधित हो रही है, तो आपको एक त्रुटि संदेश मिलेगा, जिसे आप अंतिम रूप से अंतिम-उपयोगकर्ता में अनुवाद कर सकते हैं (यह पंक्ति किसी अन्य उपयोगकर्ता द्वारा संशोधित की जा रही है)। यदि पंक्ति उपलब्ध है, तो अपने संशोधनों (अपडेट) करें, फिर जब भी आपका लेनदेन पूरा हो जाए, तब प्रतिबद्ध रहें।

2) आशावादी लॉकिंग

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

SELECT <...>
  FROM table
 WHERE id = :id
   AND marker = :marker
   FOR UPDATE NOWAIT

यदि क्वेरी पंक्ति में वापस आती है, तो अपना अपडेट करें। यदि ऐसा नहीं होता है, तो इसका मतलब यह है कि किसी ने पंक्ति को संशोधित किया है क्योंकि आपने इसे पिछली बार देखा था। आपको शुरुआत से ही प्रक्रिया को फिर से शुरू करना होगा।

नोट: यदि आपको अपने डीबी तक पहुंचने वाले सभी अनुप्रयोगों पर पूरा भरोसा है, तो आप आशावादी लॉकिंग के लिए सीधे अपडेट पर भरोसा कर सकते हैं। आप सीधे जारी कर सकते हैं:

UPDATE table
   SET <...>, 
       marker = marker + 1
 WHERE id = :id;

यदि कथन कोई पंक्ति अपडेट नहीं करता है, तो आप जानते हैं कि किसी ने इस पंक्ति को बदल दिया है और आपको सभी को शुरू करने की आवश्यकता है।

यदि सभी अनुप्रयोग इस योजना पर सहमत होते हैं, तो आप कभी किसी और द्वारा अवरुद्ध नहीं होंगे और आप अंधे अद्यतन से बचेंगे। हालाँकि, यदि आप पंक्ति को पहले से लॉक नहीं करते हैं, तो आप अभी भी अनिश्चित लॉकिंग के लिए अतिसंवेदनशील होते हैं यदि कोई अन्य एप्लिकेशन, बैच जॉब या सीधा अपडेट आशावादी लॉकिंग को लागू नहीं करता है। यही कारण है कि मैं हमेशा पंक्ति को लॉक करने की सलाह देता हूं, जो भी आपकी लॉकिंग स्कीम पसंद (प्रदर्शन हिट नगण्य हो सकती है क्योंकि आप पंक्ति को बंद करते समय पंक्ति सहित सभी मूल्यों को पुनः प्राप्त करते हैं)।

टी एल; डॉ

  • पहले से ही लॉक होने के बिना एक पंक्ति को अपडेट करना संभावित "ठंड" के लिए आवेदन को उजागर करता है। इससे बचा जा सकता है अगर सभी डीएमएल डीबी आशावादी या निराशावादी लॉकिंग को लागू करते हैं।
  • सत्यापित करें कि सेलेक्ट स्टेटमेंट रिटर्न वैल्यू किसी भी पिछले सिलेक्ट के अनुरूप है (किसी भी खोई हुई अपडेट समस्या से बचने के लिए)

5

यह उत्तर संभवतः द डेली डब्ल्यूटीएफ में एक प्रविष्टि के लिए योग्य होगा।

सही, सत्रों को ट्रेस करने और खोज के बाद USER_SOURCE- मैंने मूल कारण को ट्रैक किया

  • कारण, अनिश्चित रूप से त्रुटिपूर्ण तर्क था
  • हाल ही में, एक अपडेट स्टेटमेंट एसपी में जोड़ा गया था। अपडेट स्टेटमेंट मूल रूप से पूरी तालिका को अपडेट करेगा। जाहिरा तौर पर सवाल में डेवलपर अधिकार जोड़ने के बारे में भूल गया जहां आवश्यक बयानों को अद्यतन करने के लिए खंड।
  • अद्यतन की जा रही तालिका ऊपर बताई गई थी, सबसे अधिक लेनदेन वाली तालिकाओं में से एक और बड़ी संख्या में रिकॉर्ड थे। अद्यतन में एक लंबा समय लगेगा।
  • इसका नतीजा यह हुआ कि अन्य सत्रों में टेबल पर ताला नहीं लग पाया और वे रो-लॉक कंटेंट में बैठ गए।
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.