मैंने इससे पहले MySQL में समसामयिक समस्याओं के बारे में सुना है। पोस्टग्रेज में ऐसा नहीं है।
डिफ़ॉल्ट READ COMMITTEDलेन-देन अलगाव स्तर में निर्मित पंक्ति-स्तरीय लॉक पर्याप्त हैं।
मैं एक डेटा-संशोधित CTE (कुछ ऐसा है जो MySQL भी नहीं है) के साथ एक ही कथन का सुझाव देता हूं क्योंकि यह एक तालिका से दूसरी तालिका में मानों को पास करने के लिए सुविधाजनक है (यदि आपको इसकी आवश्यकता होनी चाहिए)। यदि आपको couponटेबल से किसी चीज की जरूरत नहीं है तो आप अलग से UPDATEऔर INSERTस्टेटमेंट के साथ भी लेन-देन का उपयोग कर सकते हैं ।
WITH upd AS (
UPDATE coupon
SET used = true
WHERE coupon_id = 123
AND NOT used
RETURNING coupon_id, other_column
)
INSERT INTO log (coupon_id, other_column)
SELECT coupon_id, other_column FROM upd;
यह एक दुर्लभ बात होनी चाहिए कि एक से अधिक लेनदेन एक ही कूपन को भुनाने की कोशिश करते हैं। उनके पास एक अद्वितीय संख्या है, है न? एक ही समय में एक से अधिक लेन-देन की कोशिश करना बहुत दुर्लभ होना चाहिए, फिर भी। (हो सकता है कि कोई एप्लिकेशन बग या सिस्टम को चलाने के लिए कोई व्यक्ति कोशिश कर रहा हो?)
जैसा कि यह हो सकता है, UPDATEकेवल एक ही लेनदेन के लिए सफल होता है , चाहे कोई भी हो। एक UPDATEएक का अधिग्रहण पंक्ति स्तर ताला प्रत्येक लक्ष्य पंक्ति को अद्यतन करने से पहले पर। यदि एक समवर्ती लेन-देन एक UPDATEही पंक्ति में करने की कोशिश करता है , तो यह पंक्ति पर लॉक को देखेगा और तब तक प्रतीक्षा करेगा जब तक कि अवरुद्ध लेनदेन समाप्त नहीं हो जाता ( ROLLBACKया COMMIT), फिर लॉक कतार में पहला होना:
यदि प्रतिबद्ध है, तो स्थिति को फिर से जाँचें। यदि यह अभी भी है NOT used, तो पंक्ति को लॉक करें और आगे बढ़ें। वरना UPDATEअब कोई योग्यता पंक्ति पाता है और करता कुछ भी नहीं कोई पंक्ति लौट रहा है, इसलिए, INSERTयह भी कुछ नहीं करता है।
यदि वापस लुढ़का हुआ है, तो पंक्ति को लॉक करें और आगे बढ़ें।
नहीं है एक दौड़ हालत के लिए कोई संभावित ।
नहीं है एक के लिए कोई संभावित गतिरोध जब तक आप एक ही लेन-देन में और अधिक लेखन डाल या अन्यथा सिर्फ एक से अधिक पंक्तियों ताला।
INSERTध्यान-मुक्त है। यदि, कुछ गलती से coupon_idपहले से ही logतालिका में है (और आपके पास एक UNIQUE या PK बाधा है log.coupon_id), तो पूरे लेनदेन को एक अद्वितीय उल्लंघन के बाद वापस कर दिया जाएगा। आपके DB में एक अवैध राज्य का संकेत देगा। यदि उपरोक्त कथन logतालिका में लिखने का एकमात्र तरीका है , तो ऐसा कभी नहीं होना चाहिए।