Database Engineering

هجرة مخططات قواعد البيانات دون توقف لتطبيقات المونوليث القديمة: استراتيجية بدون تقسيم

في عالم هندسة قواعد البيانات، لا توجد تحديات أكثر رعبًا من تطوير مخطط (Schema) لتطبيق مونوليثي قديم ضخم الحجم. غالبًا ما يؤدي النهج التقليدي المتمثل في حذف جدول، أو إضافة عمود، أو تعديل قيد إلى قفل قاعدة البيانات لمدة دقائق أو حتى ساعات، مما يفرض نافذة صيانة يتردد أصحاب المصلحة في الأعمال في الموافقة عليها. علاوة على ذلك، تعمل العديد من المنظمات تحت قيد عدم الاستعداد لتطبيقات الخدمات المصغرة (Microservices) أو تقسيم قواعد البيانات (Sharding).

تفصّل هذه الدليل استراتيجية قوية لتنفيذ هجرات مخططات قواعد البيانات دون توقف للأنظمة المونوليثية القديمة. من خلال الاستفادة من عمليات النشر التدريجي، وأنماط الكتابة المزدوجة، وعمليات DDL غير المقيدة، يمكنك تطوير نموذج بياناتك بأمان دون تقسيم وبدون مقاطعة حركة المرور الحية.

استراتيجية الهجرة ثلاثية المراحل

تكمن الفلسفة الأساسية وراء هجرات قواعد البيانات دون توقف في فصل نشر الكود عن نشر تغييرات المخطط. بالنسبة لأي تغيير كبير في المخطط - مثل إضافة عمود غير قابل للقيمة الفارغة (NOT NULL)، أو إعادة تسمية عمود، أو تغيير فهرس - نتبع عادةً نهجًا يتكون من ثلاث مراحل: التوسع، والهجرة، والانسحاب.

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

إضافة أعمدة غير قابلة للقيمة الفارغة

إضافة عمود لا يقبل القيمة الفارغة (NOT NULL) هو فخ كلاسيكي. إذا قمت بتشغيل الأمر ALTER TABLE users ADD COLUMN status VARCHAR(20) NOT NULL; ببساطة، فستحاول معظم قواعد البيانات مسح كل صف موجود وملئه بقيمة افتراضية، مما قد يؤدي إلى قفل الجدول وتسبب في حدوث تجاوزات زمنية (Timeouts).

بدلاً من ذلك، اسمح بالقيم الفارغة في البداية، وقم بتحديث الصفوف الموجودة بشكل غير متزامن، ثم فقط نفذ القيد. إليك كيف يبدو النهج التدريجي في SQL:

-- المرحلة 1: التوسع
-- أضف العمود كقابل للقيمة الفارغة لتجنب القفل الفوري أو إعادة التعبئة
ALTER TABLE users ADD COLUMN status VARCHAR(20) NULL;

-- قم بتحديث كود التطبيق لكتابة البيانات في كل من أعمدة 'old_status' و 'new_status'
-- أو ببساطة قم بتعبئة 'status' بينما يقوم التطبيق بتحديث السجلات بشكل طبيعي.

في منطق التطبيق الخاص بك، عند تحديث سجل مستخدم، تأكد من الكتابة في العمود الجديد. بالنسبة للبيانات القديمة التي لم يتم لمسها، يمكنك تشغيل مهمة خلفية لإعادة تعبئة البيانات:

-- المرحلة 2: الهجرة (مهمة خلفية)
-- قم بتحديث القيم الفارغة الموجودة على دفعات لتجنب المعاملات الطويلة
UPDATE users 
SET status = 'active' 
WHERE status IS NULL 
AND id > 10000 
AND id <= 20000; -- كرر الحلقات مع التجميع (Batching)

بمجرد تأكيد المهمة الخلفية أن العمود قد تم تعبئته بالكامل، يمكنك تنفيذ القيد بأمان:

-- المرحلة 3: الانسحاب
ALTER TABLE users ALTER COLUMN status SET NOT NULL;
-- إذا كان لديك عمود للكتابة المزدوجة، قم الآن بحذف العمود القديم
ALTER TABLE users DROP COLUMN old_status;

إعادة تسمية الجداول والأعمدة

غالبًا ما يُعتبر إعادة التسمية أمرًا عالي المخاطر لأنه يكسر الاستعلامات الحالية فورًا. للتخفيف من ذلك، استخدم العروض (Views) كطبقة تجريد. عند إعادة تسمية عمود أو جدول، قم بإنشاء اسم جديد مع الحفاظ على الاسم القديم سليمًا. قم بتحديث مخطط قاعدة البيانات لتوجيه العرض إلى الجدول الفيزيائي الجديد أو استخدم اسم العمود الجديد في الاستعلامات الجديدة.

على سبيل المثال، إذا كنت تقوم بإعادة تسمية user_id إلى account_id:

-- الخطوة 1: أضف العمود الجديد
ALTER TABLE orders ADD COLUMN account_id BIGINT;

قم بتحديث قاعدة الكود الخاصة بك لقراءة وكتابة البيانات في account_id. بمجرد التحقق من نشر الكود، يمكنك إعادة تعبئة البيانات وفي النهاية حذف العمود القديم. هذا يضمن أنه إذا فشل الكود الجديد، تظل قاعدة البيانات في حالة متوافقة مع الكود القديم.

الاستفادة من الميزات الخاصة بقواعد البيانات

تقدم أنظمة قواعد البيانات الحديثة ميزات محددة لمساعدة هذه الهجرات. على سبيل المثال، يسمح PostgreSQL بعمليات CONCURRENTLY للفهارس والقيود الفريدة، والتي لا تتطلب قفل جدول كامل. استغل هذه الميزات دائمًا عند توفرها.

-- في PostgreSQL، يسمح هذا بإنشاء الفهرس دون عرقلة عمليات الكتابة
CREATE INDEX CONCURRENTLY idx_orders_account ON orders(account_id);

اختبر دائمًا سكريبتات الهجرة في بيئة تجريبية (Staging) تعكس حجم بيانات الإنتاج. الفرق بين هجرة تستغرق 10 دقائق على مجموعة بيانات صغيرة وهجرة تستغرق 6 ساعات على مجموعة بيانات بحجم تيرابايت هو فرق كبير.

الخاتمة

لا تتطلب هجرة الأنظمة المونوليثية القديمة الخيار النووي المتمثل في التقسيم (Sharding) أو معماريات الخدمات المصغرة المعقدة. من خلال الالتزام بنمط التوسع-الهجرة-الانسحاب والانتباه إلى آليات القفل، يمكن لمهندسي قواعد البيانات قيادة التطور المستمر. تقلل هذه الاستراتيجية من المخاطر، وتحافظ على التوفر العالي، وتسمح لفريقك بالتكرار على نموذج البيانات بنفس سرعة كود التطبيق. تذكر، الهدف ليس مجرد تغيير المخطط، بل القيام بذلك دون جعل عملائك ينتظرون أبدًا.

Share: