मॉड्यूल पाठ (2/4)
दौड़ की स्थितियाँ
यह समझना कि एक डेटाबेस एक टर्मिनल पर अलगाव में कैसे काम करता है, सरल है, लेकिन वास्तविक वेब परिदृश्य में अनुरोध भेजने वाली सैकड़ों समवर्ती "नोड/पीएचपी/गो" प्रक्रियाएं होंगी। यहीं पर प्रसिद्ध रेस कंडीशंस का जन्म होता है।
"खोया हुआ अद्यतन" समस्या
लॉस्ट अपडेट तब होता है जब दो थ्रेड एक ही पुरानी पंक्ति को पढ़ते हैं, जावास्क्रिप्ट सर्वर में उस पर कुछ गणित करते हैं और फिर परिणाम को सहेजने के लिए अपडेट वापस भेजते हैं।
परिदृश्य:
- उत्पाद #5 में 10 इकाइयाँ हैं।
- उपयोगकर्ता ए एक खरीदता है (सर्वर ए "10" पढ़ता है, "9" की गणना करता है)।
- उसी मिलीसेकंड में उपयोगकर्ता B, A की खरीदारी के COMMIT चरण समाप्त होने से पहले एक और खरीद लेता है।
- सर्वर बी भी "10" पढ़ता है, "9" की गणना करता है।
- सर्वर A
UPDATE: set quantity = 9भेजता है। - सर्वर बी
UPDATE: set quantity = 9भेजता है। - दोनों सोचते हैं कि उन्होंने सफलतापूर्वक संख्या घटा दी। लेकिन अंतिम मान 8 इकाई होना चाहिए था! एक काल्पनिक खरीदारी खो गई है.
भारी लेनदेन के बिना समाधान (परमाणु अद्यतन)
गणित को बाहर पढ़ने और करने के बजाय, डीबी को इसे अपडेट के दौरान ही करने दें, जो हमेशा सिंक्रनाइज़ होता है।
-- Wrong
UPDATE products SET stock = 9 WHERE id = 5;
-- Correct and natively thread-safe
UPDATE products SET stock = stock - 1 WHERE id = 5;अधिक चरम विसंगतियाँ (डर्टी रीड्स और फैंटम)
- डर्टी रीड: आपने किसी और का अस्थायी डेटा पढ़ा है जिसकी अभी तक किसी COMMIT द्वारा पुष्टि नहीं की गई है (और अचानक रोलबैक आपको अमान्य कर सकता है)।
- फैंटम रीड्स: आप सभी पंक्तियों का स्कैन करते हैं, इस बीच एक दूसरा थ्रेड एक नया रिकॉर्ड डालता है, फिर आप उसी लेनदेन के दौरान एक और स्कैन करते हैं और आप जादुई रूप से पाते हैं कि नया रिकॉर्ड कहीं से भी प्रकट नहीं हुआ है, जो गणना की गई वित्तीय रिपोर्ट से समझौता करता है।
एक छोटे स्ट्रिंग हेरफेर के लिए ग्राहक रिकॉर्ड को परमाणु रूप से संशोधित करें।\nमान लें कि हम तारांकन जोड़ने के लिए ग्राहक के 'शहर' का नाम बदलना चाहते हैं। \nआईडी=10 वाले के लिए पंक्ति के स्वयं के मूल्य का लाभ उठाकर, '-पुराना' को वर्तमान मान में जोड़कर ऐसा करें (पोस्टग्रेज' || कॉन्सटेनेशन पाइप का उपयोग करें)।
संकेत दिखाएँ
अद्यतन ग्राहक सेट शहर = शहर || ' - पुराना' जहां आईडी = 10;
3 प्रयासों के बाद समाधान उपलब्ध है
भुगतान और कीमतों में एक क्लासिक खोया हुआ अपडेट होता है।\nमान लीजिए कि एक आपातकालीन मूल्य वृद्धि हुई है: 'ऑर्डर_आइटम' तालिका (ऑर्डर 1 के उत्पाद 1 के लिए) के 'यूनिट_प्राइस' को परमाणु रूप से 20% तक बढ़ाएं, यानी जेएस में मैन्युअल रूप से पूर्व-गणना की गई नई कीमत डालने के बजाय इसे * 1.2 से गुणा करें।
संकेत दिखाएँ
अद्यतन ऑर्डर_आइटम सेट यूनिट_प्राइस = यूनिट_प्राइस * 1.2 जहां ऑर्डर_आईडी = 1 और उत्पाद_आईडी = 1;
3 प्रयासों के बाद समाधान उपलब्ध है