لماذا تترك قاعدة البيانات المُدارة
تحلّ قواعد البيانات المُدارة مشكلة حقيقية: إنها تزيل عمليات اليوم الأول (التثبيت والنسخ المتماثل والنسخ الاحتياطية التلقائية). لكن نموذج أسعارها مصمم ليتصاعد بشكل غير خطي مع النمو. على AWS RDS، يُفوتر كل مكوّن بشكل منفصل: حوسبة النسخة، والتخزين gp3 لكل جيجابايت، وIOPS المُخصصة، وعقدة Multi-AZ الثانوية، والنسخ الاحتياطية خارج النافذة المُضمّنة، وعمليات نقل البيانات الصادرة. نسخة db.r6g.xlarge بتوافر عالٍ مع 200 جيجابايت من تخزين gp3 يمكن أن تتجاوز 800 دولار شهرياً بسهولة على us-east-1؛ عند 500 جيجابايت، تتجاوز 3000 دولار شهرياً. تعمل نفس أعباء العمل على VPS مخصص بجزء بسيط من هذه التكلفة.
التكلفة ليست المتغير الوحيد. قيود الامتدادات عائق تقني ملموس: pgvector على RDS متاح منذ 2023، لكن pg_graphql أو بعض إصدارات d_btree_gist ليست كذلك. على Supabase، الكتالوج أوسع لكنه مرتبط بالمنصة. الامتثال للبيانات هو المحرك الثالث: تخزين قاعدة البيانات في مركز البيانات الذي تختاره، دون نقل بين مناطق مُفوتر، يغير المعادلة للبُنى الخاضعة للائحة GDPR أو سياسات إقامة البيانات.
ما الذي تحتفظ به وما الذي ستديره بنفسك
- تحتفظ بـ: PostgreSQL نفسه بالإصدار الذي تختاره، وجميع بياناتك، وامتداداتك، وأدوارك وامتيازاتك، وسلاسل الاتصال بمجرد تحديث متغير
DATABASE_URL. - تحتفظ بـ: الأداء — على VPS NVMe مُحسَّن بشكل جيد، تعادل عمليات القراءة والكتابة العشوائية لـ PostgreSQL على الأقل تلك الخاصة بنسخة مُدارة من نفس الفئة.
- تدير: النسخ الاحتياطية —
pg_dumpبجدول cron، أوpg_basebackupلنسخة فيزيائية؛ يجب تخزين الملفات خارج الخادم (تخزين الكائنات، VPS ثانٍ). - تدير: التحديثات الصغيرة (تصحيحات الأمان) والترقيات الكبيرة (هجرة الإصدار) — التكرار منخفض والإجراء موثق، لكن لا أحد يطبقها نيابةً عنك.
- تدير: اتصالات SSL — إنشاء شهادة، تهيئة
ssl = onفيpostgresql.conf، فرض TLS فيpg_hba.conf؛ بدون هذا تنتقل البيانات بنص واضح. - تدير: المراقبة —
pg_stat_statementsوpg_stat_activityوتنبيهات على مساحة القرص والاتصالات النشطة؛ تختفي لوحات التحكم عند المزوّد مع قاعدة البيانات المُدارة.
قبل الهجرة — قائمة المتطلبات الأساسية
قبل تشغيل أول pg_dump، أربع نقاط تحدد نجاح الهجرة.
إصدار PostgreSQL: المصدر مقابل الوجهة. يمكن استعادة تفريغ أنتجه pg_dump من الإصدار N على الإصدار N أو أعلى، وليس أدنى. تحقق من إصدار المصدر: psql -h <endpoint> -U <user> -c 'SELECT version();'. على VPS، ثبّت نفس الإصدار الرئيسي أو أعلى من مستودع PGDG.
الامتدادات النشطة. أدرج الامتدادات المثبتة على المصدر: SELECT extname, extversion FROM pg_extension ORDER BY extname;. بعضها متاح بشكل عام (uuid-ossp وhstore وpgcrypto). أخرى تتطلب حزمة نظام إضافية أو تجميعاً من المصدر. امتدادات Supabase الخاصة (pg_graphql وpg_net وpgsodium) غير موجودة في PostgreSQL الافتراضي.
حجم قاعدة البيانات. SELECT pg_size_pretty(pg_database_size('<base>')); يعطي الحجم المنطقي. على VPS، خطط لمساحة القرص اللازمة للتفريغ نفسه، وقاعدة البيانات المستعادة، وهامش 20% لملفات WAL ومؤشرات الاستعادة المؤقتة.
الاتصالات النشطة. قاعدة البيانات تحت حركة المرور لا يمكن تفريغها بشكل نظيف مع معاملات طويلة جارية. تحقق: SELECT count(*), state FROM pg_stat_activity GROUP BY state;. إذا استمرت اتصالات بحالة idle in transaction لعدة دقائق، حدد تلك الجلسات وأنهها قبل تشغيل تفريغ الهجرة.
الهجرة من AWS RDS
يفرض RDS TLS على الاتصالات الواردة (rds.force_ssl = 1 افتراضياً على النسخ الحديثة). لذا فإن الخيار --sslmode=require ضروري على pg_dump، وإلا فإن الاتصال يُرفض أو يُنشأ بدون تشفير حسب تهيئة النسخة.
استخدم نقطة نهاية القراءة (Read Replica) للتفريغ حيثما أمكن لتجنب إضافة حمل على النسخة الأساسية أثناء الهجرة.
export PGPASSWORD='كلمة-مرورك'
pg_dump \
-h your-instance.xxxx.rds.amazonaws.com \
-U your_user \
--sslmode=require \
-Fc \
-f /tmp/dump-rds.pgc \
your_databaseثم استعد على VPS بشكل متوازٍ لتسريع الاستيراد:
pg_restore \
--no-owner \
--no-privileges \
-h localhost \
-U your_vps_user \
-d your_database \
-j 4 \
/tmp/dump-rds.pgcالخياران --no-owner و--no-privileges ضروريان: ينشئ RDS أدواراً داخلية (rdsadmin وrds_superuser) غائبة عن أي PostgreSQL خارج AWS. المتغيرات غير القابلة للنقل من RDS: rds.force_ssl وأي معلمة ذات بادئة rds. هي معلمات نظام AWS خاصة غير موجودة في postgresql.conf القياسي.
الهجرة من Google Cloud SQL
يقدم Cloud SQL مسارَي تصدير: Cloud SQL Auth Proxy (موصى به للاتصالات البرمجية) والتصدير إلى حاوية GCS (موصى به للتفريغات الكبيرة أو الهجرات أحادية الاتجاه).
عبر Cloud SQL Auth Proxy (اتصال مباشر، مناسب للقواعد < 10 جيجابايت):
cloud_sql_proxy -instances=my-project:europe-west1:my-instance=tcp:5433 &
export PGPASSWORD='your-password'
pg_dump \
-h 127.0.0.1 \
-p 5433 \
-U your_user \
-Fc \
-f /tmp/dump-cloudsql.pgc \
your_databaseعبر تصدير GCS (موصى به للقواعد الكبيرة):
gcloud sql export sql my-instance \
gs://my-bucket/dump-cloudsql.sql \
--database=your_database \
--offload
gsutil cp gs://my-bucket/dump-cloudsql.sql /tmp/
psql -h localhost -U your_vps_user -d your_database \
-f /tmp/dump-cloudsql.sqlالفخ الرئيسي لـ Cloud SQL: الخيار --offload ينقل معالجة التفريغ إلى عامل ثانوي ويقلل التأثير على النسخة الأساسية. يُنشئ Cloud SQL أيضاً مستخدم cloudsqladmin — طبّق --no-owner --no-privileges على الاستعادة كما هو الحال مع RDS.
الهجرة من Supabase
يكشف Supabase وصولاً مباشراً لـ PostgreSQL عبر URI اتصال متاح في إعدادات المشروع (Settings > Database > Connection string > URI).
export DATABASE_URL="postgresql://postgres:[email protected]:5432/postgres"
pg_dump \
"$DATABASE_URL" \
--sslmode=require \
-Fc \
--no-owner \
--no-privileges \
-f /tmp/dump-supabase.pgcالامتدادات الموجودة على Supabase والغائبة عن VPS الافتراضي. هذا هو الفخ الرئيسي عند الهجرة من Supabase:
- pgvector: متاح على Supabase، يجب تثبيته يدوياً على VPS (sudo apt install postgresql-17-pgvector على Debian/Ubuntu، ثم CREATE EXTENSION vector;).
- pg_graphql: امتداد Supabase الخاص الذي يكشف نقطة نهاية GraphQL تلقائية. غير موجود في مستودعات APT القياسية — يتطلب التجميع من المصدر (Rust + cargo-pgrx) أو إعادة كتابة طبقة الوصول GraphQL خارج قاعدة البيانات.
- pg_net: يسمح بطلبات HTTP من دوال SQL. غائب عن الحزم القياسية — أعد كتابة الاستخدامات خارج قاعدة البيانات.
- pgsodium: تشفير على مستوى قاعدة البيانات. تكامله مع Vault خاص بـ Supabase.
- http: امتداد مجتمعي متاح كـ postgresql-17-http على Debian/Ubuntu.
قبل تشغيل التفريغ، أدرج الامتدادات النشطة بشكل شامل: SELECT extname FROM pg_extension WHERE extname NOT IN ('plpgsql');
الأوامر حسب المصدر
مرّر الجدول أفقيًا
| المصدر | أمر pg_dump | الأفخاخ المعروفة | المتغير الذي يجب إعادة تهيئته |
|---|---|---|---|
| AWS RDS | `pg_dump -h <endpoint> -U <user> --sslmode=require -Fc -f dump.pgc <base>` | `--no-owner --no-privileges` مطلوب؛ أدوار `rdsadmin`/`rds_superuser` غائبة عن VPS | `rds.force_ssl` → استبدله بـ `ssl = on` في `postgresql.conf` |
| Google Cloud SQL | `pg_dump -h 127.0.0.1 -p 5433 -U <user> -Fc -f dump.pgc <base>` عبر Auth Proxy، أو `gcloud sql export sql` → حاوية GCS | `--offload` لتقليل التأثير على الأساسي؛ `--no-owner --no-privileges` ضد `cloudsqladmin` | Auth Proxy للإزالة؛ الاتصال المباشر بـ VPS كبديل |
| Supabase | `pg_dump "$DATABASE_URL" --sslmode=require -Fc --no-owner --no-privileges -f dump.pgc` | `pg_graphql` و`pg_net` و`pgsodium` غائبة عن VPS الافتراضي؛ `pgvector` للتثبيت يدوياً | URL اتصال Supabase → `DATABASE_URL` مباشر لـ VPS؛ Supabase Auth للفصل |
التحويل التدريجي بدون توقف
لقطة أولاً — حفظ المصدر في نقطة زمنية
قبل أي عملية، خذ لقطة يدوية لنسخة المصدر من وحدة تحكم المزوّد (RDS: Actions > Take snapshot؛ Cloud SQL: Operations > Create backup؛ Supabase: Settings > Backups > Trigger backup). هذه اللقطة شبكة أمانك: تتيح لك العودة إلى الحالة الدقيقة لقاعدة البيانات قبل الهجرة.
pg_dump إنتاج — تفريغ كامل لقاعدة البيانات الإنتاجية
شغّل التفريغ باستخدام الأمر المناسب لمصدرك (انظر القسم السابق). سجّل وقت البداية والنهاية للتفريغ — أي معاملات تُؤكَّد بعد بدء التفريغ لن تكون في الملف. على RDS وCloud SQL، استخدم نقطة نهاية القراءة إن كانت متاحة. تحقق من أن ملف dump.pgc غير فارغ وأكمل بدون أخطاء:
ls -lh /tmp/dump-*.pgc.pg_restore VPS — الاستعادة والتحقق الأولي
على VPS، أنشئ قاعدة البيانات الهدف واستعد:
createdb -U postgres your_database && pg_restore --no-owner --no-privileges -h localhost -U your_user -d your_database -j 4 /tmp/dump-source.pgc. بعد اكتمال الاستعادة، تحقق من أعداد الصفوف في الجداول الحيوية:SELECT relname, n_live_tup FROM pg_stat_user_tables ORDER BY n_live_tup DESC LIMIT 20;على كلا النسختين وقارن الأرقام.قراءة فقط على المصدر — تجميد قاعدة البيانات الأصلية
اختر نافذة تحويل (ليل، عطلة نهاية الأسبوع، فترة انخفاض الحركة). في بداية هذه النافذة، ضع قاعدة البيانات المصدر في وضع القراءة فقط لإيقاف الفجوة بين المصدر والوجهة:
ALTER DATABASE your_database SET default_transaction_read_only = on;. هذه الخطوة هي اللحظة الوحيدة التي يكون فيها توقف قصير للكتابة حتمياً — وعادةً ما يستغرق أقل من 30 ثانية.التحقق من أعداد الصفوف — التناسق قبل التحويل
مع المصدر في وضع القراءة فقط، شغّل فحصاً نهائياً لعدد الصفوف جدولاً بجدول:
psql -h <source> -U <user> -c 'SELECT count(*) FROM your_main_table;'وقارن معpsql -h localhost -U your_user -c 'SELECT count(*) FROM your_main_table;'. إذا استمرت فجوة، شغّل تفريغاً تدريجياً للسجلات المنشأة بعد وقت بدء التفريغ الأول وأدرجها حتى التقارب.تبديل DATABASE_URL — التطبيق يشير إلى VPS
حدّث متغير البيئة
DATABASE_URLللإشارة إلى VPS:postgresql://your_user:your-password@<VPS-IP>:5432/your_database?sslmode=require. أعد تشغيل التطبيق. تحقق من نجاح أول الاستعلامات وخلو السجلات من أخطاء الاتصال وأن الكتابات تصل إلى VPS. يبقى المصدر متاحاً في وضع القراءة فقط لـ 24 إلى 48 ساعة أخرى — لا تحذفه فوراً.
التحقق بعد الهجرة
أربعة فحوصات تجريها في الساعة التالية للتحويل.
أعداد الصفوف. على أكثر عشرة جداول حجماً، قارن أعداد المصدر والوجهة. الفجوة الصفرية تؤكد التقاط جميع المعاملات؛ فجوة متبقية من عدة صفوف قد تشير إلى معاملات كانت جارية وقت التحويل.
المجاميع الاختبارية. على الجداول الحيوية، احسب مجموعاً اختبارياً للتحكم: SELECT md5(string_agg(id::text || amount::text, ',' ORDER BY id)) FROM orders; وقارن النتيجة على كلا النسختين. المجموع المتطابق يؤكد سلامة البيانات صفاً بصف.
اختبار الامتدادات. لكل امتداد يستخدمه التطبيق، شغّل استعلام اختبار بسيط: SELECT 'test'::vector(3) لـ pgvector، SELECT gen_random_uuid() لـ pgcrypto. الامتداد المفقود أو المهيأ بشكل خاطئ يظهر فوراً.
اتصالات التطبيق. تحقق في سجلات التطبيق أن الاتصالات تُنشأ على VPS لا على قاعدة البيانات القديمة. تحقق أيضاً من نشاط اتصالات SSL: SELECT ssl, client_addr FROM pg_stat_ssl JOIN pg_stat_activity USING (pid) WHERE client_addr IS NOT NULL LIMIT 5;.
التراجع في أقل من 5 دقائق. لمدة 24 إلى 48 ساعة بعد التحويل، يبقى المصدر حياً في وضع القراءة فقط. إذا اكتُشفت مشكلة حاجبة، التراجع فوري: أعد DATABASE_URL القديم في متغير البيئة وأعد تشغيل التطبيق. لا فقدان بيانات — المصدر لم يُعدَّل منذ التحويل (هو في وضع القراءة فقط) وVPS سجّل الكتابات الجديدة منذ التحويل. لا تحذف المصدر أبداً قبل 48 ساعة من الاستقرار على VPS.
للمزيد
يغطي هذا الدليل الهجرة أحادية الاتجاه — الإجراء الأكثر شيوعاً لمغادرة مزوّد مُدار. ثلاثة مواضيع تكميلية تستحق الاستكشاف حسب سياقك.
PostgreSQL المستضاف ذاتياً مقابل Amazon RDS — مقارنة ROI مع أرقام بين النموذجين، مع عتبات حجم قاعدة البيانات وحركة المرور التي يصبح عندها الاستضافة الذاتية واضحة الأفضلية.
استضافة PostgreSQL على VPS — التهيئة التفصيلية بعد التثبيت: postgresql.conf وpg_hba.conf وpgBouncer والمراقبة والنسخ الاحتياطية والتصليب.
PostgreSQL بتوافر عالٍ مع Patroni على VPS — إذا كان اتفاقية مستوى الخدمة تتطلب failover تلقائياً، فإن Patroni على كتلة ثلاثة عقد يعيد إنتاج ضمانات RDS Multi-AZ أو Cloud SQL HA بدون علاوة المزوّد.