الانتقال إلى المحتوى الرئيسي
الوحدة 11 · الدرس 2 من 442/57 في الدورة~10 min
دروس الوحدة (2/4)

ظروف السباق

إن فهم كيفية عمل قاعدة البيانات بشكل منفصل على محطة واحدة أمر بسيط، ولكن في سيناريو الويب الحقيقي سيكون هناك مئات من عمليات "Node/PHP/Go" المتزامنة التي ترسل الطلبات. هذا هو المكان الذي تولد فيه شروط السباق الشهيرة.

مشكلة "التحديث المفقود".

يحدث التحديث المفقود عندما يقرأ خيطان نفس الصف القديم، ويقومان ببعض العمليات الحسابية عليه في خادم JavaScript ثم يرسلان التحديث مرة أخرى لحفظ النتيجة.

سيناريو:

  • المنتج #5 يحتوي على 10 وحدات.
  • يشتري المستخدم "أ" واحدًا (يقرأ الخادم "10"، ويحسب "9").
  • في نفس المللي ثانية، يشتري المستخدم "ب" آخر قبل أن تنتهي عملية الشراء "أ" من مرحلة الالتزام.
  • يقرأ الخادم B أيضًا الرقم "10"، ويحسب الرقم "9".
  • يرسل الخادم "أ" UPDATE: set quantity = 9.
  • يرسل الخادم "ب" UPDATE: set quantity = 9.
  • كلاهما يعتقد أنهما قلصا الرقم بنجاح. لكن القيمة النهائية كان ينبغي أن تكون 8 وحدات! تم فقدان عملية الشراء الوهمية.

الحل بدون معاملات ثقيلة (التحديثات الذرية)

بدلاً من القراءة وإجراء العمليات الحسابية في الخارج، اسمح لقاعدة البيانات بالقيام بذلك أثناء التحديث نفسه، والذي تتم مزامنته دائمًا.

SQL
-- Wrong
UPDATE products SET stock = 9 WHERE id = 5;

-- Correct and natively thread-safe
UPDATE products SET stock = stock - 1 WHERE id = 5;

المزيد من الحالات الشاذة الشديدة (القراءات القذرة والأشباح)

  • قراءة متسخة: تقرأ بيانات مؤقتة لشخص آخر لم يتم تأكيدها بعد بواسطة COMMIT (ويمكن أن تنتقل فجأة إلى ROLLBACK مما يؤدي إلى إبطال مفعولك).
  • القراءات الوهمية: تقوم بإجراء مسح لجميع الصفوف، وفي الوقت نفسه يقوم مؤشر ترابط ثانٍ بإدراج سجل جديد، ثم تقوم بإجراء فحص آخر أثناء نفس المعاملة وتجد بطريقة سحرية أن السجل الجديد ظهر من العدم، مما يضر بالتقارير المالية المحسوبة.
تمرين#sql.m11.l2.e1
المحاولات: 0جارٍ التحميل…

قم بتعديل سجل العملاء تلقائياً لمعالجة سلسلة صغيرة.\nلنفترض أننا نريد إعادة تسمية "مدينة" العميل لإضافة علامة النجمة. \nقم بذلك عن طريق الاستفادة من قيمة الصف الخاصة للصف الذي له المعرف=10، مع ربط ' - Old' بالقيمة الحالية (استخدم أنبوب التسلسل || postgres).

جارٍ تحميل المحرر…
إظهار التلميح

تحديث العملاء SET المدينة = المدينة || ' - قديم' حيث المعرف = 10؛

الحل متاح بعد 3 من المحاولات

تمرين#sql.m11.l2.e2
المحاولات: 0جارٍ التحميل…

يحدث تحديث كلاسيكي مفقود في الدفعات والأسعار.\nلنفترض أن هناك ارتفاعًا طارئًا في الأسعار: قم بزيادة "سعر_الوحدة" في جدول "عناصر_الطلب" (للمنتج 1 من الطلب 1) بنسبة 20% ذريًا، أي ضربه في * 1.2 بدلاً من إدراج السعر الجديد المحسوب مسبقًا يدويًا في JS.

جارٍ تحميل المحرر…
إظهار التلميح

تحديث order_items SET Unit_price = Unit_price * 1.2 حيث order_id = 1 AND Product_id = 1؛

الحل متاح بعد 3 من المحاولات