المستوى المطلوب: متوسط. المقال ده موجّه لمهندس عنده أساس في SQL وبيتعامل مع قاعدة بيانات فيها بيانات حقيقية على الإنتاج. لو لسه بتتعلّم، متقلقش: كل فكرة صعبة هنشرحها بمثال بسيط الأول، وبعدين نرجع نحطّها في تعريف دقيق.
تقدر تغيّر عمودًا في جدول فيه 50 مليون صف والموقع شغّال، من غير ثانية توقف واحدة. الشرط إنك متعملش التغيير في خطوة واحدة. الطريقة اسمها Expand-Contract، وهي المعيار في الفرق اللي بتنشر كل يوم.
الترحيل بدون توقف: نمط Expand-Contract للتعديل على جداول عليها ملايين الصفوف
الافتراض إنك على PostgreSQL 11 أو أحدث، وعندك جدول فيه ملايين الصفوف، وحركة كتابة مستمرة عليه. لو جدولك صغير (أقل من 100 ألف صف) الموضوع كله مش هيفرق معاك، وممكن تتجاهل المقال ده وتعمل ALTER عادي.
المشكلة باختصار
عايز تحوّل عمود phone النصّي الفوضوي لعمود منظّم phone_e164 بصيغة موحّدة. الطريقة اللي في بالك: تعمل ALTER TABLE، تنسخ البيانات، وتعدّل الكود. الطريقة دي بتفشل تحت الضغط، لأن بعض أوامر ALTER بتقفل الجدول كله لثوانٍ أو دقائق، وفي الوقت ده كل طلب كتابة أو قراءة بيقف في الطابور. النتيجة: أخطاء timeout ومستخدمين متعلّقين.
ليه ALTER المباشر بيوقّع الموقع؟ (المفهوم بمثال ثم علميًا)
المثال: تخيّل مطعم شغّال ومليان زباين، وعايز تغيّر محطة التقطيع في المطبخ. لو وقفت المطبخ كله عشان تفكّها وتركّب واحدة جديدة، كل الطلبات هتقف. الطريقة الذكية: تبني المحطة الجديدة جنب القديمة، تشغّل الاتنين مع بعض شوية، تنقل الطبخ بالتدريج، وبعد ما تتأكد إن الجديدة شغّالة، تفكّ القديمة في وقت فاضي. المطعم مقفلش لحظة.
علميًا: أوامر زي ALTER TABLE ... ALTER COLUMN TYPE أو إضافة عمود بقيمة افتراضية متغيّرة بتاخد قفل ACCESS EXCLUSIVE، وده أقوى قفل في PostgreSQL: بيمنع أي قراءة أو كتابة على الجدول لحد ما العملية تخلص. على 50 مليون صف ممكن ده يفضل دقايق. نمط Expand-Contract بيفصل تغيير المخطط عن تغيير الكود، فتفضل النسخة القديمة والجديدة شغّالين مع بعض، وميحصلش قفل طويل في أي لحظة.
الحل: Expand ثم Backfill ثم Contract
الفكرة إنك تخلّي العمودين موجودين مع بعض فترة، فأي نشر للكود ميحتاجش المخطط القديم والجديد يتغيّروا في نفس اللحظة.
- Expand: ضيف العمود الجديد فاضي (nullable). ده بياخد قفل لجزء من الثانية بس.
- خلّي التطبيق يكتب في العمودين مع بعض (dual-write) في أي صف جديد أو معدّل.
- Backfill: انسخ البيانات القديمة على دفعات صغيرة، مش دفعة واحدة.
- Contract: بعد ما تتأكد إن العمود الجديد مكتمل، حوّل التطبيق يقرا منه بس، وبعدها احذف العمود القديم.
أول خطوة، الـ Expand، وهي رخيصة: