ماڈیول اسباق (2/4)
ریس کے حالات
یہ سمجھنا کہ ڈیٹا بیس کس طرح ایک ٹرمینل پر تنہائی میں کام کرتا ہے، لیکن ایک حقیقی ویب منظر نامے میں درخواستیں بھیجنے کے لیے سیکڑوں ہم آہنگ "نوڈ/پی ایچ پی/گو" عمل ہوں گے۔ یہ وہ جگہ ہے جہاں ریس کے مشہور حالات پیدا ہوتے ہیں۔
"کھوئے ہوئے اپ ڈیٹ" کا مسئلہ
گمشدہ اپ ڈیٹ اس وقت ہوتا ہے جب دو تھریڈز ایک ہی پرانی قطار کو پڑھتے ہیں، جاوا اسکرپٹ سرور میں اس پر کچھ ریاضی کریں اور پھر نتیجہ کو بچانے کے لیے اپ ڈیٹ واپس بھیجیں۔
منظر:
- پروڈکٹ #5 میں 10 یونٹ ہیں۔
- صارف A خریدتا ہے (سرور A "10" پڑھتا ہے، "9" کی گنتی کرتا ہے)۔
- اسی ملی سیکنڈ میں صارف B دوسرا خریدتا ہے اس سے پہلے کہ A کی خریداری COMMIT مرحلہ مکمل کر لے۔
- سرور B بھی "10" پڑھتا ہے، "9" کی گنتی کرتا ہے۔
- سرور A
UPDATE: set quantity = 9بھیجتا ہے۔ - سرور B
UPDATE: set quantity = 9بھیجتا ہے۔ - دونوں سوچتے ہیں کہ انہوں نے کامیابی سے تعداد میں کمی کی ہے۔ لیکن حتمی قیمت 8 یونٹ ہونی چاہیے تھی! ایک پریت کی خریداری کھو گئی ہے۔
بھاری لین دین کے بغیر حل (ایٹمی اپڈیٹس)
باہر ریاضی پڑھنے اور کرنے کے بجائے، DB کو اپ ڈیٹ کے دوران ہی کرنے دیں، جو ہمیشہ مطابقت پذیر ہوتا ہے۔
-- 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یہ id=10 والے کے لیے قطار کی اپنی قدر کا فائدہ اٹھاتے ہوئے، ' - پرانے' کو موجودہ قدر سے جوڑ کر کریں (پوسٹگریس استعمال کریں' || کنکٹنیشن پائپ)۔
اشارہ دکھائیں۔
اپ ڈیٹ کسٹمرز SET city = city || '- پرانا' جہاں id = 10؛
3 کوششوں کے بعد حل دستیاب ہے۔
ادائیگیوں اور قیمتوں میں ایک کلاسک گمشدہ اپ ڈیٹ ہوتا ہے۔\nآئیے کہتے ہیں کہ قیمتوں میں ایک ہنگامی اضافہ ہوا ہے: 'order_items' ٹیبل کی 'unit_price' (order 1 کے پروڈکٹ 1 کے لیے) جوہری طور پر 20% اضافہ کریں، یعنی JS میں نئی قیمت کو دستی طور پر داخل کرنے کے بجائے اسے * 1.2 سے ضرب دیں۔
اشارہ دکھائیں۔
آرڈر_آئٹمز کو اپ ڈیٹ کریں یونٹ_قیمت = یونٹ_قیمت * 1.2 جہاں آرڈر_id = 1 اور پروڈکٹ_id = 1؛
3 کوششوں کے بعد حل دستیاب ہے۔