मैंने इससे पहले 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
तालिका में लिखने का एकमात्र तरीका है , तो ऐसा कभी नहीं होना चाहिए।