1. نظرة عامة على آلية الهجرة
1.1 المفهوم والدور لعملية الهجرة
عملية هجرة قاعدة البيانات هي عملية مزامنة التغييرات في نماذج البيانات مع هيكل قاعدة البيانات، وهي أمر حاسم لاستمرارية البيانات. مع تطوير إصدار التطبيق، يتعرض نموذج البيانات لتغييرات، مثل إضافة أو حذف الحقول، أو تعديل الفهارس. تتيح الهجرة للمطورين إدارة هذه التغييرات بطريقة مُرقمة ومنهجية، مضمنة التناسق بين هيكل قاعدة البيانات ونموذج البيانات.
في تطوير الويب الحديث، توفر آلية الهجرة الفوائد التالية:
- التحكم بالإصدارات: يمكن لملفات الهجرة تتبع تاريخ تغيير هيكل قاعدة البيانات، مما يجعل من السهل التراجع وفهم التغييرات في كل إصدار.
- النشر التلقائي: من خلال آلية الهجرة، يمكن أتمتة نشر قاعدة البيانات وتحديثاتها، مما يقلل من إمكانية التدخل اليدوي وخطر الأخطاء.
- التعاون بين الفرق: تضمن ملفات الهجرة استخدام أعضاء الفريق لهياكل قاعدة البيانات المتزامنة في بيئات التطوير المختلفة، مما يسهل التطوير التشاركي.
1.2 ميزات الهجرة في إطار ent
تقدم تكامل إطار ent
مع آلية الهجرة الميزات التالية:
-
البرمجة الإعلانية: يحتاج المطورون فقط للتركيز على التمثيل البرمجي للكيانات، وسيتولى إطار
ent
تحويل الكيانات إلى جداول قاعدة البيانات. -
الهجرة التلقائية: يمكن لـ
ent
إنشاء وتحديث هياكل جداول قاعدة البيانات تلقائيًا دون الحاجة إلى كتابة تعليمات DDL يدويًا. -
التحكم المرن: يوفر
ent
خيارات تكوينية متنوعة لدعم متطلبات الهجرة المختلفة، مثل مع أو بدون قيود المفتاح الخارجي، وإنشاء معرفات فريدة عالميًا.
2. مقدمة عن الهجرة التلقائية
2.1 المبادئ الأساسية للهجرة التلقائية
تعتمد ميزة الهجرة التلقائية لإطار ent
على ملفات تعريف النموذج (تُوجد عادةً في دليل ent/schema
) لإنشاء هيكل قاعدة البيانات. بعد تعريف المطورين للكيانات والعلاقات، سيقوم ent
بفحص الهيكل الحالي في قاعدة البيانات وإنشاء العمليات المقابلة لإنشاء الجداول، أو إضافة أو تعديل الأعمدة، وإنشاء الفهارس، وما إلى ذلك.
علاوة على ذلك، تعمل مبدأ الهجرة التلقائية في ent
بنمط "الإضافة": حيث يُضيف افتراضيًا فقط جداول جديدة، وفهارس جديدة، أو يُضيف أعمدة إلى الجداول، ولا يقوم بحذف الجداول أو الأعمدة الحالية. يعد هذا التصميم مفيدًا لمنع فقدان البيانات عن طريق الخطأ ويُسهل توسيع هيكل قاعدة البيانات بطريقة تسير نحو الأمام.
2.2 استخدام الهجرة التلقائية
الخطوات الأساسية لاستخدام الهجرة التلقائية في ent
على النحو التالي:
package main
import (
"context"
"log"
"ent"
)
func main() {
client, err := ent.Open("mysql", "root:pass@tcp(localhost:3306)/test")
if err != nil {
log.Fatalf("Failed to connect to MySQL: %v", err)
}
defer client.Close()
ctx := context.Background()
// أداء الهجرة التلقائية لإنشاء أو تحديث هيكل قاعدة البيانات
if err := client.Schema.Create(ctx); err != nil {
log.Fatalf("Failed to create database schema: %v", err)
}
}
في الكود أعلاه، يتولى ent.Open
إنشاء اتصال مع قاعدة البيانات وإرجاع مثيل العميل، في حين يُقوم client.Schema.Create
بتنفيذ عملية الهجرة التلقائية الفعلية.
3. تطبيقات متقدمة للهجرة التلقائية
3.1 حذف الأعمدة والفهارس
في بعض الحالات، قد نحتاج إلى حذف الأعمدة أو الفهارس التي لم تعد مطلوبة من هيكل قاعدة البيانات. في هذا الوقت، يمكننا استخدام خيارات WithDropColumn
و WithDropIndex
. على سبيل المثال:
// تشغيل الهجرة مع الخيارات لحذف الأعمدة والفهارس.
err = client.Schema.Create(
ctx,
migrate.WithDropIndex(true),
migrate.WithDropColumn(true),
)
يُمكن تمكين تلك المقطع من التكوين لحذف الأعمدة والفهارس أثناء الهجرة التلقائية. سيقوم ent
بحذف أي أعمدة وفهارس غير موجودة في تعريف الهيكل عند تنفيذ الهجرة.
3.2 مُعرّف فريد عالميًا
بشكل افتراضي، تبدأ المفاتيح الأساسية في قواعد البيانات الخاصة بـ SQL من الرقم 1 لكل جدول، وقد تشترك أنواع الكيان المختلفة في نفس المعرف. في بعض سيناريوهات التطبيق، مثل استخدام GraphQL، قد يكون من الضروري توفير الفرادة العالمية لمعرفات الكائنات لأنواع كيان مختلفة. في ent
، يمكن تكوين ذلك باستخدام الخيار WithGlobalUniqueID
:
// تشغيل الهجرة مع مُعرّفات فريدة عالميًا لكل كيان.
if err := client.Schema.Create(ctx, migrate.WithGlobalUniqueID(true)); err != nil {
log.Fatalf("Failed to create the database schema: %v", err)
}
بعد تمكين خيار WithGlobalUniqueID
، سيرسل ent
مدى 2^32 على كل كيان في جدول يحمل اسم ent_types
لتحقيق الفرادة العالمية.
3.3 وضع عدم الاتصال
يُسمح وضع عدم الاتصال بكتابة تغييرات النظام إلى io.Writer
بدلاً من تنفيذها مباشرة على قاعدة البيانات. إنه مفيد للتحقق من أوامر SQL قبل حدوث التغييرات، أو لإنشاء سيناريو SQL للتنفيذ اليدوي. على سبيل المثال:
// قم بتفريغ تغييرات التهجير إلى ملف
f، err := os.Create("migrate.sql")
إذا كان err != nil {
log.Fatalf("فشل إنشاء ملف التهجير: %v", err)
}
defer f.Close()
إذا كان err := client.Schema.WriteTo(ctx, f); err != nil {
log.Fatalf("فشل طباعة تغييرات نظام قاعدة البيانات: %v", err)
}
سيقوم هذا الكود بكتابة تغييرات التهجير إلى ملف يُسمى migrate.sql
. في التطبيق العملي، يمكن للمطورين اختيار الطباعة مباشرة على الإخراج القياسي أو الكتابة إلى ملف لمراجعة أو للحفظ.
4. دعم المفاتيح الخارجية والسنانيات المخصصة
4.1 تمكين أو تعطيل المفاتيح الخارجية
في Ent، يتم تنفيذ المفاتيح الخارجية عن طريق تعريف العلاقات (حواف) بين الكيانات، وتُنشئ هذه العلاقات تلقائيًا على مستوى قاعدة البيانات لفرض سلامة البيانات واستمراريتها. ومع ذلك، في بعض الحالات، مثل تحسين الأداء أو عندما لا تدعم قاعدة البيانات المفاتيح الخارجية، قد تختار تعطيلها.
لتمكين أو تعطيل قيود المفاتيح الخارجية في عمليات التهجير، يمكنك التحكم في ذلك من خلال خيار التكوين WithForeignKeys
:
// تمكين المفاتيح الخارجية
err = client.Schema.Create(
ctx,
migrate.WithForeignKeys(true),
)
إذا كان err != nil {
log.Fatalf("فشل إنشاء موارد النظام مع المفاتيح الخارجية: %v", err)
}
// تعطيل المفاتيح الخارجية
err = client.Schema.Create(
ctx,
migrate.WithForeignKeys(false),
)
إذا كان err != nil {
log.Fatalf("فشل إنشاء موارد النظام بدون المفاتيح الخارجية: %v", err)
}
يجب تمرير هذا الخيار التكوين عند استدعاء Schema.Create
، ويحدد ما إذا كان يتم تضمين قيود المفاتيح الخارجية في DDL المولد استنادًا إلى القيمة المحددة.
4.2 تطبيق الخطايا المخصصة للتهجير
الخطايا المخصصة للتهجير هي منطق مخصص يمكن إدراجه وتنفيذه في مراحل مختلفة من تنفيذ التهجير. إنها مفيدة لأداء منطق معين على قاعدة البيانات قبل/بعد التهجير، مثل التحقق من نتائج التهجير وملء البيانات المسبقة.
فيما يلي مثال على كيفية تنفيذ خطايا التهجير المخصصة:
func customHook(next schema.Creator) schema.Creator {
return schema.CreateFunc(func(ctx context.Context, tables ...*schema.Table) error {
// الكود المخصص الذي سيتم تنفيذه قبل التهجير
// على سبيل المثال، تسجيل، التحقق من شروط معينة، إلخ.
log.Println("منطق مخصص قبل التهجير")
// استدعاء الخطوة التالية أو المنطق المخصص الافتراضي
err := next.Create(ctx, tables...)
إذا كان err != nil {
return err
}
// الكود المخصص الذي سيتم تنفيذه بعد التهجير
// على سبيل المثال، تنظيف، تهاجير البيانات، فحوص الأمان، إلخ.
log.Println("منطق مخصص بعد التهجير")
return nil
})
}
// استخدام الخطايا المخصصة في التهجير
err := client.Schema.Create(
ctx,
schema.WithHooks(customHook),
)
إذا كان err != nil {
log.Fatalf("خطأ في تطبيق خطايا التهجير المخصصة: %v", err)
}
الخطايا هي أدوات قوية وضرورية لعمليات التهجير المعقدة، حيث تمنحك القدرة على التحكم المباشر في سلوك تهجير قاعدة البيانات عند الحاجة.
5. عمليات التهجير المخططة
5.1 مقدمة لعمليات التهجير المخططة
عملية التهجير المخططة هي نمط لإدارة تهجيرات قاعدة البيانات، مما يتيح للمطورين تقسيم تغييرات هيكل القاعدة إلى عدة إصدارات، كل منها يحتوي على مجموعة محددة من أوامر تعديل قاعدة البيانات. بالمقارنة مع عملية التهجير التلقائية، توفر عملية التهجير المخططة تحكمًا دقيقًا، مما يضمن تتبع التغييرات في هيكل القاعدة وقابليتها للعكس.
الميزة الرئيسية لعملية التهجير المخططة هي دعمها لعمليات التهجير الأمامية والخلفية (أي الترقية أو الهبوط)، مما يتيح للمطورين تطبيق التغييرات الخاصة، أو التراجع عنها، أو تخطيها حسب الحاجة. عند التعاون داخل فريق العمل، تضمن عملية التهجير المخططة أن يعمل كل عضو على هيكل قاعدة بيانات موحد، مما يقلل من المشكلات الناشئة عن عدم الاتساق.
يكون تغيير الهيكل التلقائي غالبًا ما يكون لا رجعة فيه، حيث يقوم بإنشاء وتنفيذ البيانات والتعبيرات SQL لتتناسب مع أحدث حالة نماذج الكيانات، وهو يستخدم أساسًا في مراحل التطوير أو المشاريع الصغيرة.
5.2 استخدام عمليات التهجير المخططة
1. تثبيت أداة Atlas
قبل استخدام الهجرة النسخية، يجب عليك تثبيت أداة Atlas
على نظامك. Atlas
هي أداة هجرة تدعم أنظمة قواعد البيانات المتعددة، وتوفر ميزات قوية لإدارة تغييرات هيكل قاعدة البيانات.
macOS + Linux
curl -sSf https://atlasgo.sh | sh
Homebrew
brew install ariga/tap/atlas
Docker
docker pull arigaio/atlas
docker run --rm arigaio/atlas --help
Windows
https://release.ariga.io/atlas/atlas-windows-amd64-latest.exe
2. إنشاء ملفات الهجرة استنادًا إلى تعريفات الكيان الحالية
atlas migrate diff migration_name \
--dir "file://ent/migrate/migrations" \
--to "ent://ent/schema" \
--dev-url "docker://mysql/8/ent"
3. ملفات الهجرة للتطبيق
بمجرد توليد ملفات الهجرة، يمكن تطبيقها على بيئات التطوير، الاختبار، أو الإنتاج. عادةً، ستقوم أولاً بتطبيق هذه الملفات على قاعدة بيانات التطوير أو الاختبار للتأكد من تنفيذها كما هو متوقع. ثم، سيتم تنفيذ نفس خطوات الهجرة في بيئة الإنتاج.
atlas migrate apply \
--dir "file://ent/migrate/migrations" \
--url "mysql://root:pass@localhost:3306/example"
استخدم أمر atlas migrate apply
، محددًا مجلد ملفات الهجرة (--dir
) وعنوان URL لقاعدة البيانات المستهدفة (--url
) لتطبيق ملفات الهجرة.