قد تُنفَّذ عملية ترحيل قاعدة البيانات مرتين عندما يعتقد أكثر من مسار بدء تشغيل أو حاوية أو مجدول أن خطوة الترقية نفسها تقع ضمن مسؤوليته.
غالبًا ما تُطلق التطبيقات المستضافة ذاتيًا عمليات الترحيل من نقطة دخول أو عملية ويب أو عامل أو حاوية جانبية أو وحدة systemd أو خطاف نشر. بعد إعادة النشر، قد تتداخل حاوية قديمة مع أخرى جديدة، أو قد تعيد سياسة إعادة التشغيل تشغيل مُرحِّل فشل، أو قد تصل نسختان متماثلتان إلى قاعدة البيانات قبل أن تسجّل إحداهما اكتمال العملية. ينبغي أن يحدّد التشخيص كل مُشغِّل محتمل، وأن يثبت ما إذا كان إطار الترحيل يستخدم قفلًا دائمًا أو سجلًا لتاريخ المخطط قبل بدء إصلاح أي بيانات.
حدّد كل عملية يمكنها تشغيل الترحيل
ابحث عن أمر الترحيل في نقطة دخول الصورة، وأمر Compose، وأمر العامل، ووحدة systemd، ومهمة cron، ونص النشر، وسجل بدء تشغيل التطبيق. سجّل معرّفات العمليات وأسماء الحاويات في وقتَي التنفيذ.
يمكن لـ Docker Compose بدء الخدمات وفقًا للتبعيات المعلنة، لكن ترتيب بدء التشغيل وحده لا يجعل ترحيل التطبيق مملوكًا لجهة واحدة. توضّح إرشادات ترتيب بدء التشغيل الرسمية سبب كون توفر قاعدة البيانات وامتلاك الترحيل بشكل حصري شرطين منفصلين.
إذا ظهر الأمر نفسه في كلٍّ من نقطة دخول الويب وخدمة ترحيل مخصصة، فأزل أحد المالكين. وإذا لم يوجد سوى أمر واحد، فتابع بالتحقق من النسخ المتماثلة وحلقات إعادة التشغيل وسجلات حالة الترحيل.
تحقّق من تداخل الحاويات القديمة والجديدة
اعرض الحاويات قيد التشغيل، والتي تعيد التشغيل، والتي خرجت، واليتيمة أثناء النشر. قارن أسماء المشاريع، وأسماء الخدمات، ومعرّفات الحاويات، والطوابع الزمنية للإنشاء.
توضح وثائق systemd أن سياسة إعادة تشغيل الخدمة يمكنها إعادة تشغيل أمر فاشل وفقًا لإعدادات الوحدة. ويساعد نموذج إعادة تشغيل الخدمة في تفسير سبب إمكانية أن يعيد مُشغِّل على المضيف تشغيل الترحيل بعد خروج المحاولة المستندة إلى الحاوية برمز خطأ.
أزل المُشغِّلات اليتيمة التي ثبت أنها غير لازمة فقط بعد حفظ سجلاتها. وغالبًا ما يعكس ظهور طابع زمني ثانٍ للترحيل بعد الأول بوقت قصير إعادة محاولة، لا مهمة مجدولة منفصلة.
استخدم قفلًا لقاعدة البيانات قبل تطبيق تغييرات المخطط
حدّد ما إذا كان التطبيق يحصل على قفل على مستوى قاعدة البيانات قبل قراءة حالة الترحيل وتطبيق التغييرات. اختبر محاولتَي بدء تشغيل متزامنتين في بيئة قابلة للتخلص منها.
يوفّر PostgreSQL أقفالًا استشارية للتنسيق الذي تحدده التطبيقات، ما يسمح لمُشغِّل ترحيل واحد بمنع آخر حتى عند بدء كليهما في الوقت نفسه تقريبًا.
يجب أن يغطي القفل نافذة القرار والتنفيذ كاملة. إذ إن التحقق من إصدار المخطط الحالي قبل الحصول على القفل لا يزال يسمح لمُشغِّلين باختيار الترحيل المعلّق نفسه.
تحقّق من دلالات القفل في MySQL أو MariaDB
بالنسبة إلى التطبيقات المتوافقة مع MySQL، افحص ما إذا كانت أداة الترحيل تستخدم قفلًا مسمّى أو معاملة أو جدول أقفال، وما إذا كان الاتصال يظل حيًا طوال عملية الترحيل.
توثّق MySQL الأقفال المسمّاة المرتبطة بالاتصال، والتي تُحرَّر عند انتهاء الجلسة المالكة، ولذلك يجب الحصول عليها بأمان من جديد بعد حدوث عطل أو إعادة تشغيل.
قد يؤدي فشل الاتصال إلى تحرير القفل قبل أن يسجّل إطار الترحيل اكتمال العملية. قارن سجلات قاعدة البيانات بالطوابع الزمنية لإعادة تشغيل الحاوية لتحديد هذا التسلسل.
افحص جدول سجل إطار الترحيل
اعرض معرّفات عمليات الترحيل، وترتيب التنفيذ، وعلامات النجاح، والمجاميع الاختبارية، والطوابع الزمنية. قارن التشغيلين المسجلين بالسجلات التي أُثبتت فعليًا في قاعدة البيانات.
يستخدم Flyway جدولًا لسجل المخطط لتتبّع عمليات الترحيل المطبقة وحالاتها.
إذا غيّر التشغيل الأول المخطط لكنه فشل قبل تسجيل النجاح، فقد يعيد التشغيل الثاني محاولة ترحيل لم تُكتب بطريقة تجعله قابلًا للتنفيذ بأمان أكثر من مرة. أصلح السجل فقط بعد مقارنة المخطط الفعلي بالنتيجة المتوقعة للترحيل.
تحقّق من هوية سجل التغييرات وتغيّر المجموع الاختباري
قارن أسماء ملفات الترحيل ومعرّفاتها ومؤلفيها ومساراتها ومجاميعها الاختبارية قبل تحديث الصورة وبعده. حدّد ما إذا كانت الصورة تحتوي على إدخالات سجل تغييرات مكررة أو معاد تسميتها.
يسجّل Liquibase التغييرات المنفذة في جدول DATABASECHANGELOG، حيث تعتمد هوية التغيير على معرّفه ومؤلفه ومسار ملفه.
قد يؤدي نقل ملف سجل التغييرات أو إعادة إنشاء المعرّفات إلى جعل العمل القديم يبدو جديدًا حتى عندما تكون تعليمات SQL متشابهة. أعد هوية الترحيل المستقرة بدلًا من حذف نطاقات واسعة من السجل يدويًا.
أعد النشر مع مالك واحد للترحيل وتحقّق من قابلية التنفيذ بأمان أكثر من مرة
اختر مالكًا واحدًا للترحيل، وأضف قفلًا دائمًا، واجعل خدمتي الويب والعامل تنتظران اكتمال العملية بنجاح، ثم أعد النشر في نسخة اختبارية من قاعدة البيانات.
تقدّم مقالة ZimaSpace حول حدود جدولة الحاويات قاعدة مرتبطة: ينبغي أن تكون لكل مهمة صيانة جهة تشغيل واحدة مثبتة.
تُحل المشكلة عندما تؤدي عمليات البدء المتزامنة أو المتكررة إلى تطبيق ترحيل واحد، وإنشاء سجل تاريخ دائم واحد، وعدم حدوث تغيير ثانٍ في المخطط بعد إعادة التشغيل.
الأسئلة الشائعة
هل يؤدي تشغيل الترحيل مرتين دائمًا إلى إتلاف قاعدة البيانات؟
لا. قد تتمكن عمليات الترحيل القابلة للتنفيذ بأمان أكثر من مرة من اكتشاف الكائنات الموجودة والتعامل معها بأمان، لكن تحويلات البيانات غير القابلة للتكرار، أو إنشاء الفهارس، أو تغييرات الأعمدة قد تفشل أو تؤدي إلى تكرار البيانات.
هل ينبغي السماح لكل نسخة متماثلة من الويب بتشغيل عمليات الترحيل؟
فقط عندما يوفّر الإطار تنسيقًا موثوقًا على مستوى قاعدة البيانات. ويكون تخصيص مالك واحد لترحيل يُنفَّذ مرة واحدة أسهل في التدقيق ضمن عملية نشر خادم منزلي.
هل يمكنني وضع علامة اكتمال الترحيل يدويًا؟
فقط بعد إثبات أن المخطط والبيانات الفعلية يطابقان النتيجة المتوقعة للترحيل. فقد يؤدي تعديل السجل أولًا إلى إخفاء تغيير طُبّق جزئيًا.
الدعم والنصائح
المزيد للقراءة

لماذا تؤدي استعادة وحدة تخزين Docker إلى إعادة إنشاء محتويات الملفات مع فقدان السمات الموسّعة؟
تشخيص لاستعادة وحدة تخزين يغطي جرد السمات الموسَّعة (xattr)، وخيارات tar وRsync، ومساحات الأسماء، ودعم الوجهة، والامتيازات، والتسميات، والبيانات الوصفية للتطبيق، والاختبارات.

لماذا يحتفظ الحاوي قيد التشغيل بحد الذاكرة القديم بعد تغيير ملف Compose؟
تشخيص لحدود الذاكرة يغطي مجموعات cgroups النشطة، وإعادة التشغيل مقابل إعادة الإنشاء، وحقول Compose، والحدود الصارمة والمرنة، والنطاقات الأصلية، وذاكرة التبديل، وأكوام الذاكرة في...

لماذا يؤدي إعادة تشغيل وكيل عكسي إلى إبطال كل جلسة في تطبيق مستضاف ذاتيًا واحد؟
تشخيص لفقدان الجلسة يشمل نطاق إعادة التشغيل، وملكية ملفات تعريف الارتباط، وتدوير الأسرار، والجلسات المدعومة بالتخزين المؤقت، والتوجيه الثابت، وبوابات المصادقة، والاسترداد.

