PostgreSQL
 sql >> डेटाबेस >  >> RDS >> PostgreSQL

क्या एकाधिक धागे बाध्य सेट पर डुप्लिकेट अपडेट का कारण बन सकते हैं?

आपकी बताई गई गारंटी इस साधारण मामले में लागू होती है, लेकिन जरूरी नहीं कि थोड़े अधिक जटिल प्रश्नों में हो। उदाहरण के लिए उत्तर का अंत देखें।

साधारण मामला

यह मानते हुए कि col1 अद्वितीय है, ठीक एक मान "2" है, या स्थिर क्रम है इसलिए प्रत्येक UPDATE उसी क्रम में समान पंक्तियों से मेल खाता है:

इस क्वेरी के लिए क्या होगा कि थ्रेड्स को col=2 के साथ पंक्ति मिल जाएगी और सभी उस टुपल पर राइट लॉक को हथियाने का प्रयास करेंगे। उनमें से कोई एक ही सफल होगा। अन्य पहले थ्रेड के लेन-देन के प्रतिबद्ध होने की प्रतीक्षा को रोक देंगे।

वह पहला tx 1 की पंक्ति गणना लिखेगा, प्रतिबद्ध करेगा और लौटाएगा। कमिट लॉक जारी करेगा।

अन्य टीएक्स फिर से ताला हथियाने की कोशिश करेंगे। वे एक-एक करके सफल होंगे। बदले में प्रत्येक लेनदेन निम्नलिखित प्रक्रिया से गुजरेगा:

  • प्रतियोगी टपल पर राइट लॉक प्राप्त करें।
  • WHERE col=2 की दोबारा जांच करें ताला लगने के बाद की स्थिति।
  • पुन:जांच से पता चलेगा कि शर्त अब मेल नहीं खाती है इसलिए UPDATE उस पंक्ति को छोड़ देंगे।
  • UPDATE कोई अन्य पंक्तियाँ नहीं हैं इसलिए यह शून्य पंक्तियों को अद्यतन करने की रिपोर्ट करेगा।
  • प्रतिबद्ध करें, अगले tx को पकड़ने की कोशिश करने के लिए लॉक जारी करें।

इस साधारण मामले में पंक्ति-स्तर लॉकिंग और स्थिति पुन:जांच प्रभावी ढंग से अद्यतनों को क्रमबद्ध करती है। अधिक जटिल मामलों में, इतना नहीं।

आप इसे आसानी से प्रदर्शित कर सकते हैं। चार psql सत्र खोलें। पहले में, टेबल को BEGIN; LOCK TABLE test; . बाकी सत्रों में एक जैसे UPDATE चलते हैं s - वे टेबल लेवल लॉक पर ब्लॉक कर देंगे। अब लॉक को COMMIT . द्वारा छोड़ दें अपना पहला सत्र टिंग। उन्हें दौड़ देखो। केवल एक 1 की पंक्ति गणना की रिपोर्ट करेगा, अन्य 0 की रिपोर्ट करेंगे। यह आसानी से स्वचालित है और पुनरावृत्ति और अधिक कनेक्शन/थ्रेड तक स्केलिंग के लिए स्क्रिप्टेड है।

अधिक जानने के लिए, समवर्ती लेखन के नियम पढ़ें। , PostgreSQL समवर्ती मुद्दों का पृष्ठ 11 - और फिर उस प्रस्तुति का शेष भाग पढ़ें।

और अगर col1 अद्वितीय नहीं है?

जैसा कि केविन ने टिप्पणियों में उल्लेख किया है, अगर col अद्वितीय नहीं है इसलिए आप कई पंक्तियों से मेल खा सकते हैं, फिर UPDATE . के विभिन्न निष्पादन अलग-अलग ऑर्डर मिल सकते हैं। ऐसा तब हो सकता है जब वे अलग-अलग योजनाएँ चुनते हैं (जैसे कि एक PREPARE . के माध्यम से होती है और EXECUTE और दूसरा प्रत्यक्ष है, या आप enable_ . के साथ खिलवाड़ कर रहे हैं GUCs) या यदि वे जिस योजना का उपयोग करते हैं, वह अस्थिर प्रकार के समान मूल्यों का उपयोग करती है। यदि वे पंक्तियों को एक अलग क्रम में प्राप्त करते हैं तो tx1 एक टपल को लॉक कर देगा, tx2 दूसरे को लॉक कर देगा, फिर वे प्रत्येक एक दूसरे के पहले से लॉक किए गए टुपल्स पर लॉक प्राप्त करने का प्रयास करेंगे। PostgreSQL उनमें से एक को गतिरोध अपवाद के साथ निरस्त कर देगा। यह एक और अच्छा कारण है कि क्यों सभी आपका डेटाबेस कोड हमेशा होना चाहिए लेन-देन का पुन:प्रयास करने के लिए तैयार रहें।

यदि आप यह सुनिश्चित करने के लिए सावधान हैं कि समवर्ती UPDATE s हमेशा समान पंक्तियों को उसी क्रम में प्राप्त करें, आप अभी भी उत्तर के पहले भाग में वर्णित व्यवहार पर भरोसा कर सकते हैं।

निराशा की बात यह है कि PostgreSQL UPDATE ... ORDER BY . की पेशकश नहीं करता है इसलिए यह सुनिश्चित करना कि आपके अपडेट हमेशा एक ही क्रम में समान पंक्तियों का चयन करते हैं, उतना आसान नहीं है जितना आप चाहते हैं। ए SELECT ... FOR UPDATE ... ORDER BY उसके बाद एक अलग UPDATE अक्सर सबसे सुरक्षित होता है।

अधिक जटिल क्वेरी, क्यूइंग सिस्टम

यदि आप कई चरणों के साथ प्रश्न कर रहे हैं, जिसमें कई टुपल्स शामिल हैं, या समानता के अलावा अन्य स्थितियां हैं, तो आप आश्चर्यजनक परिणाम प्राप्त कर सकते हैं जो एक सीरियल निष्पादन के परिणामों से भिन्न होते हैं। विशेष रूप से, किसी भी चीज़ के समवर्ती रन जैसे:

UPDATE test SET col = 1 WHERE col = (SELECT t.col FROM test t ORDER BY t.col LIMIT 1);

या एक साधारण "कतार" प्रणाली बनाने के अन्य प्रयास करेंगे आप जिस तरह की उम्मीद करते हैं, उस तरह से काम करने में *असफल*। देखें Concurrency पर PostgreSQL डॉक्स और यह प्रस्तुति अधिक जानकारी के लिए।

यदि आप एक डेटाबेस द्वारा समर्थित एक कार्य कतार चाहते हैं तो अच्छी तरह से परीक्षण किए गए समाधान हैं जो सभी आश्चर्यजनक रूप से जटिल कोने के मामलों को संभालते हैं। सबसे लोकप्रिय में से एक है PgQ . एक उपयोगी PgCon पेपर है। विषय पर, और 'postgresql कतार' के लिए एक Google खोज उपयोगी परिणामों से भरा है।

BTW, LOCK TABLE . के बजाय आप उपयोग कर सकते हैं SELECT 1 FROM test WHERE col = 2 FOR UPDATE; टुपल पर सिर्फ एक राइट लॉक प्राप्त करने के लिए। यह इसके खिलाफ अपडेट को ब्लॉक कर देगा, लेकिन अन्य टुपल्स को राइट ब्लॉक नहीं करेगा या किसी भी रीड को ब्लॉक नहीं करेगा। इससे आप विभिन्न प्रकार के समवर्ती मुद्दों का अनुकरण कर सकते हैं।




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. मैं PostgreSQL के साथ पासवर्ड कैसे एन्क्रिप्ट करूं?

  2. PostgreSQL array_agg(INTEGER[])

  3. PostgreSQL में JS Date.now () को कैसे सेव करें?

  4. कोई पासवर्ड नहीं दिया गया / स्थितीय पैरामीटर नहीं मिला PostgreSQL - Powershell

  5. पायथन / psycopg2 का उपयोग करके एक बड़ी PostgreSQL तालिका में एक कॉलम को कुशलतापूर्वक कैसे अपडेट करें?