جودة البرمجيات / متوسط: أدلة المنتج المتكامل / الدرس 8
سلامة قاعدة البيانات والمعاملات والتزامن
حوّل قواعد البيانات إلى ثوابت قابلة للملاحظة وحالات تكامل مستهدفة. افحص القيم الخالية والتفرد والتراجع والتنافس على المقاعد دون استخدام سجلات الإنتاج.
في هذه الصفحة
أهداف الدرس
- اختبار القيود ومعالجة التطبيق بصورة منفصلة.
- تصميم حالات التراجع والكتابة المتزامنة.
- شرح حدود الاختبار المرتبطة بمحرك قاعدة البيانات.
وصف الحالة التي يجب أن تبقى صحيحة
في الورشة يجب ألا يتجاوز التسجيل النشط السعة، وأن يشير كل تسجيل إلى متعلم ودورة موجودين، وألا يملك متعلم تسجيلين نشطين مكررين. هذه ثوابت حالة. يناسب بعضها المفاتيح الأساسية والأجنبية وقيود التفرد، بينما قد تحتاج السعة عبر عدة صفوف إلى تصميم تطبيقي بمعاملة. اختبر إنفاذ القاعدة ومعالجة التطبيق لرفض الكتابة. لا تحل رسالة تحقق لطيفة محل حماية دائمة من عملية ثانية تكتب في الوقت نفسه.
حالة محلولة: الخالي ليس عدداً سالباً
يجب أن يحوي عمود الرسم عدداً صحيحاً معروفاً غير سالب. في PostgreSQL لا يرفض CHECK (fee_cents >= 0) وحده NULL، لأن القيد يقبل نتيجة غير معلومة. أضف NOT NULL إذا ألزمت القاعدة بوجود قيمة. جرّب الصفر والموجب والسالب وNULL كعمليات منفصلة في مخطط معزول. توقّع قبول الأولين فقط. واختبر تحويل رفض الكتابة إلى خطأ التطبيق الآمن المتفق عليه بدلاً من كشف تفاصيل القاعدة للمستخدم.
CREATE TABLE fee_demo (
id integer PRIMARY KEY,
fee_cents integer NOT NULL CHECK (fee_cents >= 0)
);
-- Independent cases: 0 -> accept; 500 -> accept; -1 -> reject; NULL -> reject.
يعبر القيدان عن التزامين مختلفين. نفّذ العبارات المرفوضة منفصلة أو استخدم نقاط حفظ؛ إذ تحتاج معاملة PostgreSQL الفاشلة إلى استعادة قبل عبارات أخرى.
يجب أن يمر اختبار المعاملة بنقطة إخفاق ذات معنى
افترض أن تأكيد التسجيل ينشئ صفاً وينقص السعة الباقية. أدخل خطأ مضبوطاً بعد الكتابة الأولى وقبل الاكتمال، ثم افحص من اتصال مستقل بعد التراجع. توقّع عدم وجود تسجيل جزئي أو فقد سعة. قد يخفي اختبار يحيط كل شيء بتراجعه الخاص كيفية اعتماد التطبيق أو رؤية اتصال آخر للحالة. اختر العزل عمداً وأعد تجهيز البيانات بين الحالات. وثّق ترتيب العمليات ليبرهن الدليل التعافي من عمل جزئي لا الرفض قبل بدء أي عمل.
حالة محلولة: محاولتان على مقعد واحد
جهّز سعة واحد دون تسجيلات نشطة. نسق عميلين مضبوطين ليحاولا الحجز انطلاقاً من الحالة نفسها. الثابت هو نجاح تسجيل واحد على الأكثر وعدم سلبية السعة، أياً كان الفائز. افحص استجابة الخاسر وأعداد القاعدة النهائية. لا يمثل بدء طلبين متتابعين اختبار تزامن؛ استخدم حاجز اختبار أو جدولة مضبوطة للوصول إلى نقطة التنافس. كرر ترتيبات مختارة مع الإقرار بأن جداول تنفيذ قليلة لا تثبت الصحة لكل تنفيذ ممكن.
الحالة الأولية | عمليتان متنافستان | الدليل النهائي المطلوب
السعة=1، التسجيل=0 | حجز A وحجز B | نجاح=1؛ صف نشط=1؛ المتبقي=0
إخفاق بعد كتابة الصف | تأكيد A | الصفوف النشطة=0؛ المتبقي=1
لا تفترض الفحوص هوية الفائز، لكنها تشترط نتيجة واحدة متسقة.
مطابقة دلالات القاعدة المهمة
قد يختلف البديل في الذاكرة عن المحرك المستخدم في القفل وترتيب NULL والمقارنة والقيود وعزل المعاملات. استخدم البدائل السريعة حين تقبل افتراضاتها، وفحوص تكامل مستهدفة على المحرك المقصود لهذه المخاطر. اختبر الترحيلات ببيانات قديمة مصطنعة ممثلة وتحقق من القيم المحولة والقيود، لا مجرد نجاح التنفيذ. لا تستخدم قاعدة الإنتاج كتجهيز سهل. وثّق إصدار المحرك وإعداد العزل مع أدلة التزامن؛ فهذه التفاصيل تؤثر في التفسير أكثر بكثير من عبارة عامة «نجح اختبار القاعدة».
الأخطاء الشائعة وإصلاحها
اعتبار نجاح SQLite دليلاً على قفل PostgreSQL
- لماذا يحدث؟
- اختلاف دلالات البديل عن المحرك المستهدف.
- كيف تصلحه؟
- تشغيل اختبارات تنافس مستهدفة على نسخة معزولة من المحرك.
- كيف تتجنب تكراره؟
- تصنيف المخاطر الخاصة بالمحرك صراحة.
افتراض أن CHECK يمنع NULL
- لماذا يحدث؟
- إغفال منطق SQL ذي القيم الثلاث.
- كيف تصلحه؟
- إضافة NOT NULL واختباره حين يلزم.
- كيف تتجنب تكراره؟
- إدراج القيم الغائبة في مصفوفة اختبارات القيود.
اختبار تنافس يرسل طلبات متتابعة فقط
- لماذا يحدث؟
- عدم مشاركة الحالة المتنافس عليها بصورة متزامنة.
- كيف تصلحه؟
- تنسيق العمليات عند حاجز مضبوط.
- كيف تتجنب تكراره؟
- وصف ترتيب التنفيذ المختبر والثابت النهائي.
اختبر فهمك
1. يُفحص التفرد قبل INSERT. لماذا تختبر قيد القاعدة أيضاً؟
اعرض الحل المشروح
قد يرى عميلان عدم وجود الصف قبل أن يكتب أيهما. يحمي قيد التفرد الحالة الدائمة، وعلى التطبيق معالجة الكتابة الخاسرة بأمان. اختبر إدراجين متكافئين متزامنين وتوقّع صفاً واحداً ونجاحاً واحداً ونتيجة التكرار المتفق عليها.
2. كيف تتحقق من ترحيل المبالغ العشرية إلى سنتات؟
اعرض الحل المشروح
جهّز قيماً قديمة مصطنعة منها صفر و12.34 والحدود المسموحة؛ طبّق التقريب الموثق وتوقّع 0 و1234 للمثالين الأولين. افحص سياسة NULL وأعداد الصفوف والمعرفات والقيود الجديدة. لا يثبت نجاح أمر الترحيل وحده صحة القيم.
أهم ما تعلمته
- اختبر الثوابت الدائمة ومعالجة رفض الكتابة التي يراها المستخدم.
- تحتاج أدلة التزامن إلى تداخل مضبوط وسياق قاعدة واضح.