[{"data":1,"prerenderedAt":169},["ShallowReactive",2],{"seo-verification":3,"blog-ترقية-postgresql-من-الإصدار-15-إلى-17-في-docker-ar":6},{"google":4,"bing":5},"EycwPY2XMyTkVzas3n1ygeNJFGAH513qrMjfDljzsMQ","",{"id":7,"slug":8,"slugs":9,"title":13,"excerpt":14,"readTime":15,"views":16,"isPinned":17,"publishedAt":18,"category":19,"categories":25,"featuredImage":27,"bgImage":28,"posterImage":29,"relatedSolution":27,"intro":30,"sections":31,"ctaTitle":110,"ctaBody":111,"ctaButton":112,"ctaUrl":113,"relatedPosts":114},315,"ترقية-postgresql-من-الإصدار-15-إلى-17-في-docker",{"fr":10,"en":11,"ar":8,"es":12},"postgresql-15-17-migration-docker-vps","migrating-postgresql-15-to-17-in-a-docker-stack","migrar-postgresql-15-a-17-en-una-stack-docker","ترقية PostgreSQL من الإصدار 15 إلى 17 في Docker","دليل كامل لترقية PostgreSQL 15 إلى 17 في Docker: pg_dump\u002Fpg_restore، الامتدادات غير المتوافقة، وقائمة تحقق لترقية بدون توقف — وحالة Supabase.",12,0,false,"2026-08-30T00:00:00+00:00",{"id":20,"name":21,"slug":22,"color":23,"icon":24},6,"قواعد البيانات","bases-de-donnees","bg-teal-500\u002F10 text-teal-400","database",[26],{"id":20,"name":21,"slug":22,"color":23,"icon":24},null,"\u002Fblog\u002Fcovers\u002Fbg.svg","\u002Fblog\u002Fcovers\u002Fpostgresql-15-17-migration-docker-vps-poster.svg","يصل PostgreSQL 15 إلى نهاية دعمه الرسمي في نوفمبر 2026. قامت Supabase بالتحول بشكل صامت إلى `postgres:17` في يونيو 2026، مما أدى إلى تعطل البيئات المستضافة ذاتيًا التي لم تُثبّت إصدار الصورة. إذا كانت بيئة Compose لا تزال تعمل على PG 15، فإن نافذة الترقية مفتوحة — وتضيق. يفصّل هذا الدليل الامتدادات غير المتوافقة، ويوثّق التغييرات السلوكية الحقيقية بين PG 15 وPG 17، ويقدم إجراء ترقية بدون توقف قابلًا للتطبيق على أي بيئة Compose إنتاجية.",[32,36,47,50,69,72,75,95,98,107],{"type":33,"title":34,"body":35},"h2","لماذا الترقية الآن — نهاية دعم PG 15 وإشارة Supabase","يصل PostgreSQL 15 إلى نهاية دعمه الرسمي في **نوفمبر 2026**. بعد هذا التاريخ، لن تصدر مجموعة تطوير ‏PostgreSQL Global Development Group أي تصحيحات أمنية أو إصلاحات للأخطاء.\n\nلكن الترقية لا تحتمل الانتظار حتى نوفمبر لسبب أكثر إلحاحًا: **قامت Supabase بالتحول إلى صورة مرجعية `postgres:17` في يونيو 2026** (النقاش رقم 46080 في سجل التغييرات العام). البيئات التي تشير إلى `image: supabase\u002Fpostgres` دون تثبيت إصدار تلقّت PG 17 عند تنفيذ `docker compose pull` التالي، دون أي تحذير مرئي في سجلات البدء.\n\nإذا كانت بيئتك تُثبّت بالفعل `postgres:15`، فأنت محمي على المدى القصير. أما إذا كانت تشير إلى `postgres:latest` أو وسم Supabase متحرك، فقد تكون قد انتقلت بالفعل دون علمك. التحقق يتم بأمر واحد:\n\n```bash\ndocker exec \u003Ccontainer> psql -U postgres -c 'SELECT version();'\n```\n\nلا تفترض — تحقق.",{"type":37,"title":38,"items":39},"ul","ما الذي يتغير فعلًا بين PG 15 وPG 17",[40,41,42,43,44,45,46],"**تشديد `search_path` منذ PG 15.1** (ADV-2022-00007)‏: لم يعد مخطط `public` مدرجًا في `search_path` الافتراضي للأدوار غير المشرف. أي استعلام يفترض `public.my_table` دون تأهيل صريح قد يعيد 0 صف بصمت بدلًا من إرجاع خطأ.","**`pg_dump` ينتج نسخًا احتياطية غير متوافقة للأسفل**‏: لا يمكن استعادة نسخة PG 17 على PG 15. العكس مدعوم، وهذا هو اتجاه الترقية. احتفظ بنسخ PG 15 الاحتياطية لمدة 30 يومًا على الأقل بعد التحويل.","**رفع القيمة الافتراضية لـ `wal_level` إلى `logical` في PG 16+**‏: إذا كان `postgresql.conf` يُجبر `wal_level = minimal`، سيتغير السلوك بعد الترقية. قد تصبح فتحات النسخ المتماثل المنطقي الموجودة غير صالحة.","**حذف الدوال القديمة**: `lo_import`، `lo_export` وبعض دوال `pg_catalog` تم حذفها أو إعادة تسميتها بين PG 15 وPG 17 — تحقق من الدوال المستخدمة في امتداداتك المخصصة.","**‏`pg_stat_statements` يعدّل تطبيع الاستعلامات**: لوحات Grafana\u002FPgHero التي تجمع بـ query fingerprint ستبدأ من الصفر بعد الترقية.","**`pg_partman`** (إدارة التقسيم) يتطلب الإصدار ≥ 5.x لـ PG 17 — الإصدار 4.x غير متوافق.","**`timescaledb`** يتطلب الإصدار ≥ 2.13 لـ PG 17; الإصدارات السابقة ترفض التحميل وتوقف بدء تشغيل الحاوية.",{"type":33,"title":48,"body":49},"جرد الامتدادات: ما يمر وما يكسر","قبل أي ترقية، استخرج قائمة الامتدادات النشطة في كل قاعدة بيانات:\n\n```bash\ndocker exec \u003Cpg15_container> psql -U postgres -c \\\n  \"SELECT datname, extname, extversion FROM pg_extension e JOIN pg_database d ON d.oid = e.extnamespace ORDER BY datname, extname;\"\n```\n\n**الامتدادات المتوافقة دون إجراء**‏: `pgcrypto`‏، `uuid-ossp`‏، `hstore`‏، `ltree`‏، `citext`‏، `pg_trgm`‏، `unaccent`‏، `intarray`‏، `tablefunc`‏.\n\n**الامتدادات التي تتطلب تحديثًا**‏: `pgvector` (الترقية إلى ≥ 0.7.0 لـ PG 17)‏، `PostGIS` (‏≥ 3.4 لـ PG 17)‏، `TimescaleDB` (≥ 2.13 إلزامي)‏، `pg_partman` (≥ 5.0 إلزامي)‏.\n\nأمر التحقق بعد الترقية:\n\n```bash\ndocker exec \u003Cpg17_container> psql -U postgres -d mydb \\\n  -c 'SELECT extname, extversion FROM pg_extension ORDER BY extname;'\n```\n\nقارن عمود `installed_version` مع جرد PG 15 — الامتداد المفقود (`NULL`) يشير إلى مشكلة في التحميل يجب حلها قبل التحقق من صحة الترقية.",{"type":51,"title":52,"steps":53},"steps","إجراء الترقية بدون توقف: pg_dump\u002Fpg_restore",[54,57,60,63,66],{"title":55,"body":56},"تثبيت إصدار صورة PG 15","قبل أي عملية، **ثبّت الصورة الحالية** في ملف `docker-compose.yml` الخاص بك بوسمها الدقيق:\n\n```bash\ndocker inspect \u003Cpg15_container> --format '{{.Config.Image}}'\n# مثال: postgres:15.7\n# حدّث Compose:\n# image: postgres:15.7\n```\n\nأودع هذا التغيير في نظام إدارة الإصدارات قبل المتابعة. لا يمكن إجراء الترقية في مكانها: يرفض PG 17 البدء على بيانات `PGDATA` الخاصة بـ PG 15.",{"title":58,"body":59},"التقاط النسخ الاحتياطية العالمية وقواعد البيانات","صدّر أولًا الكائنات العالمية (الأدوار، والمساحات)، ثم كل قاعدة بيانات على حدة:\n\n```bash\n# الكائنات العالمية\ndocker exec \u003Cpg15_container> pg_dumpall \\\n  -U postgres \\\n  --globals-only \\\n  > backup_globals.sql\n\n# كل قاعدة بيانات تطبيق\ndocker exec \u003Cpg15_container> pg_dump \\\n  -U postgres \\\n  --no-owner \\\n  --no-acl \\\n  --format=custom \\\n  --file=\u002Ftmp\u002Fmydb_pg15.dump \\\n  mydb\n\ndocker cp \u003Cpg15_container>:\u002Ftmp\u002Fmydb_pg15.dump .\u002Fmydb_pg15.dump\n```\n\nتحقق من سلامة النسخة الاحتياطية قبل المتابعة:\n\n```bash\npg_restore --list mydb_pg15.dump | head -20\n```",{"title":61,"body":62},"تشغيل حاوية PG 17 بالتوازي على منفذ مختلف","أضف خدمة ثانية في `docker-compose.yml` لـ PG 17 **على منفذ مختلف** (مثلًا 5433)، مع وحدة تخزين بيانات جديدة. تبقى خدمة PG 15 نشطة طوال هذه الخطوة — دون انقطاع لتطبيقاتك:\n\n```yaml\n  postgres17:\n    image: postgres:17\n    environment:\n      POSTGRES_USER: ${POSTGRES_USER}\n      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}\n      POSTGRES_DB: ${POSTGRES_DB}\n    volumes:\n      - pg17_data:\u002Fvar\u002Flib\u002Fpostgresql\u002Fdata\n    ports:\n      - \"5433:5432\"\n    shm_size: 256mb\n    healthcheck:\n      test: [\"CMD-SHELL\", \"pg_isready -U ${POSTGRES_USER}\"]\n      interval: 5s\n      timeout: 3s\n      retries: 5\n\nvolumes:\n  pg17_data:\n```\n\nشغّل هذه الخدمة فقط:\n\n```bash\ndocker compose up -d postgres17\ndocker compose exec postgres17 pg_isready\n```",{"title":64,"body":65},"الاستعادة على PG 17 والتحقق من الامتدادات","استعد الكائنات العالمية أولًا، ثم قاعدة البيانات:\n\n```bash\n# الأدوار والمساحات\ndocker exec -i \u003Cpg17_container> psql -U postgres \u003C backup_globals.sql\n\n# استعادة قاعدة البيانات\ndocker cp mydb_pg15.dump \u003Cpg17_container>:\u002Ftmp\u002Fmydb_pg15.dump\n\ndocker exec \u003Cpg17_container> pg_restore \\\n  -U postgres \\\n  --no-owner \\\n  --no-acl \\\n  -d mydb \\\n  \u002Ftmp\u002Fmydb_pg15.dump\n```\n\nإذا أبلغ pg_restore عن أخطاء في الامتدادات، أصلحها قبل المتابعة:\n\n```bash\ndocker exec \u003Cpg17_container> psql -U postgres -d mydb \\\n  -c 'CREATE EXTENSION IF NOT EXISTS pgvector;'\n```",{"title":67,"body":68},"تحويل التطبيقات والتحقق","ضع تطبيقاتك في وضع الصيانة أو للقراءة فقط، ثم قم بتحديث متغير `DATABASE_URL` لكل خدمة تطبيق للإشارة إلى حاوية PG 17 على المنفذ 5432. أعد تشغيل خدمات التطبيق:\n\n```bash\ncurl -sf http:\u002F\u002Flocalhost\u002Fapi\u002Fhealth | jq .database\n```\n\nإذا اجتازت عملية التحقق، أوقف حاوية PG 15، وأعد تعيين المنفذ 5432 إلى `postgres17`.",{"type":70,"body":71},"tip","**`search_path` هو التغيير الصامت الأكثر شيوعًا.** منذ PG ‏15.1، لم يعد مخطط `public` مدرجًا في `search_path` الافتراضي للأدوار غير المشرف. إذا فشلت ترحيلات Flyway أو Liquibase أو بيانات Artisan الأولية بخطأ `relation \"X\" does not exist` بعد الترقية، أضف `SET search_path TO public, \"$user\";` في بداية الجلسة أو أهّل أسماء جداولك صراحةً.",{"type":33,"title":73,"body":74},"حالة Supabase: postgres:17 بدون تحذير","توثّق المناقشة رقم 46080 في سجل تغييرات Supabase العام (‏github.com\u002Forgs\u002Fsupabase\u002Fdiscussions\u002F46080‏) التحول إلى `postgres:17` الذي جرى في يونيو 2026. البيئات المستضافة ذاتيًا التي تشير إلى `image: supabase\u002Fpostgres` دون وسم إصدار تلقّت PG 17 عند تنفيذ `docker compose pull` التالي، دون ترقية تلقائية للبيانات.\n\nالسلوك الملاحظ: تبدأ حاوية PG 17، وترفض قراءة `PGDATA` الخاص بـ PG 15 (التنسيق غير متوافق)، وتتوقف فورًا. سجلات الخطأ في الحاوية:\n\n```bash\ndocker logs \u003Csupabase_db_container> 2>&1 | head -20\n# FATAL: database files are incompatible with server\n# DETAIL: The data directory was initialized by PostgreSQL version 15, which is not compatible with this version 17.\n```\n\nأفضل ممارسة لأي نشر Supabase مستضاف ذاتيًا هي تثبيت الوسم بإصدار ثانوي دقيق في `docker-compose.yml`:\n\n```yaml\n  db:\n    image: supabase\u002Fpostgres:15.8.1.040\n    # أو أحدث إصدار 17.x بعد اكتمال الترقية\n    # image: supabase\u002Fpostgres:17.4.1.016\n```",{"type":76,"title":77,"headers":78,"rows":82},"comparison","استراتيجيات الترقية: pg_dump\u002Frestore مقابل pg_upgrade مقابل النسخ المتماثل المنطقي",[79,80,81],"الاستراتيجية","مدة التوقف","التعقيد",[83,87,91],[84,85,86],"pg_dump \u002F pg_restore (هذا الدليل)","5-30 دقيقة حسب حجم البيانات","منخفض — أدوات أصلية، قابلة للتكرار",[88,89,90],"pg_upgrade في المكان","1-5 دقائق (ترقية ثنائية سريعة)","مرتفع — يتطلب PG 15 وPG 17 معًا، صعب في Docker",[92,93,94],"النسخ المتماثل المنطقي (صفر توقف حقيقي)","أقل من دقيقة","مرتفع جدًا — يتطلب `wal_level = logical` وفتحات النسخ المتماثل",{"type":33,"title":96,"body":97},"استكشاف الأخطاء: الأخطاء الشائعة وأسبابها","الأخطاء الأكثر شيوعًا أثناء ترقية PG 15 إلى 17 في بيئة Docker:\n\n**`FATAL: database files are incompatible with server`**\nالسبب: بدأت حاوية PG 17 على نفس وحدة التخزين الخاصة بـ PG 15. الحل: استخدم دائمًا وحدة تخزين جديدة لـ PG 17 واستعد عبر `pg_restore`.\n\n**`ERROR: extension \"timescaledb\" is not available`** (أو `pg_partman`، `pg_cron`)\nالسبب: الامتداد غير مترجم لـ PG 17 في صورة `postgres:17` الرسمية. الحل: استخدم صورة مشتقة تحتوي على الامتدادات المطلوبة (مثل `timescale\u002Ftimescaledb:latest-pg17`).\n\n**`ERROR: role \"X\" already exists`** عند استعادة الكائنات العالمية\nالسبب: النسخة الاحتياطية `pg_dumpall --globals-only` تتضمن `CREATE ROLE` لجميع الأدوار. الحل: استخدم `--if-not-exists` أو احذف سطور `CREATE ROLE postgres` من `backup_globals.sql` قبل الاستعادة.\n\n**`ERROR: relation \"public.X\" does not exist`** في التطبيقات\nالسبب: تغيير `search_path` الافتراضي منذ PG 15.1. الحل: أضف `options=-csearch_path=public` إلى سلسلة الاتصال، أو نفّذ `ALTER ROLE app_user SET search_path = 'public';` بعد الاستعادة.\n\n**`pg_restore: error: invalid byte sequence for encoding \"UTF8\"`**\nالسبب: بيانات مرمّزة بـ `LATIN1` في PG 15 وتمت تهيئة PG 17 بـ `UTF8`. الحل: استعد على مثيل PG 17 تمت تهيئته باستخدام `POSTGRES_INITDB_ARGS: --encoding=LATIN1`.",{"type":37,"title":99,"items":100},"قائمة التحقق من التحويل — تحقق بالترتيب قبل كل خطوة",[101,102,103,104,105,106],"**قبل البدء**‏: قائمة الامتدادات النشطة مستخرجة (`pg_extension`)، إصدار PG 15 مثبّت في Compose، النسخة الاحتياطية الكاملة مُتحقَّق منها (`pg_restore --list` بدون أخطاء).","**بعد الاستعادة على PG 17**‏: جميع الامتدادات موجودة بالإصدار الصحيح، تم التحقق من `search_path` عبر دور التطبيق (ليس مشرفًا)، مقارنة عدد الصفوف في الجداول الخمسة الحيوية بين PG 15 وPG 17.","**قبل تحويل التطبيق**‏: إعلان نافذة الصيانة، تفعيل وضع القراءة فقط إن أمكن، التقاط آخر نسخة احتياطية من PG 15.","**بعد تحويل التطبيق**‏: نقطة نهاية `\u002Fhealth` تعيد 200 مع `database: ok`، سجلات التطبيق بدون أخطاء `relation does not exist`.","**الاحتفاظ بـ PG 15**‏: الاحتفاظ بوحدة تخزين PG 15 لمدة 30 يومًا على الأقل، النسخ الاحتياطية لمدة 90 يومًا، توثيق إجراء التراجع.","**بعد الترقية**‏: تشغيل `ANALYZE VERBOSE;` على جميع قواعد البيانات لإعادة حساب إحصائيات المخطط، التحقق من نشاط `autovacuum`، تحديث المراقبة لـ PG 17.",{"type":33,"title":108,"body":109},"إدارة الترقية عبر محفظة عملاء","بالنسبة لوكالة تدير بيئات عملاء متعددة، فإن ترقية PG 15 إلى 17 ليست حدثًا منفردًا — بل هي عمل يجب التخطيط له عبر المحفظة.\n\n**الجرد أولًا.** الأمر التالي يسرد جميع إصدارات PostgreSQL قيد التشغيل على VPS يستضيف مشاريع Compose متعددة:\n\n```bash\ndocker ps --format '{{.Names}}' | xargs -I{} sh -c \\\n  'docker exec {} psql -U postgres -qtAX -c \"SELECT current_setting(\\\"server_version\\\")\" 2>\u002Fdev\u002Fnull && echo \" \u003C- {}\"'\n```\n\nتحديد الأولويات حسب المخاطر: البيئات التي تحتوي على امتدادات مترجمة مخصصة أو `timescaledb`\u002F`pg_partman` تحتاج إلى صورة مشتقة مختبرة قبل التحويل.\n\nتوحيد الصورة: تعريف صورة مشتركة في سجل داخلي (`registry.yourcompany.com\u002Fpostgres:17-base`) تحتوي على الامتدادات التي تحققت منها الوكالة. جميع مشاريع Compose في المحفظة تشير إلى هذه الصورة.\n\nالنسخ الاحتياطية اليومية المضمّنة في خطط Agency على ServOrbit توفر شبكة أمان لكل ترقية: إذا أظهرت بيئة عميل سلوكًا غير متوقع في الـ 24 ساعة التالية للتحويل، تبدأ الاستعادة من نسخة احتياطية من اليوم السابق.","ترقية مخططة، محفظة تحت السيطرة","الوكالات التي تدير بيئات عملاء متعددة لا تستطيع تحمّل اكتشاف انقطاع في مساء ترقية تلقائية للإصدار. تقوم ServOrbit بمركزة إدارة VPS لمحافظ العملاء — بنية تحتية محكومة، تحديثات مخططة، نسخ احتياطية يومية مضمّنة في خطط Agency.","عرض خطط الوكالات","\u002Fsolutions\u002Fagences",[115,133,150],{"id":116,"slug":117,"slugs":118,"title":122,"excerpt":123,"readTime":124,"views":16,"isPinned":17,"publishedAt":125,"category":126,"categories":127,"featuredImage":27,"bgImage":28,"posterImage":129,"relatedSolution":130},60,"استضافة-supabase-على-خادم-vps",{"fr":119,"en":120,"ar":117,"es":121},"heberger-supabase-vps","hosting-supabase-on-a-vps","alojar-supabase-en-un-vps","استضافة Supabase على خادم VPS في 2026","استضِف Supabase ذاتيًا على VPS: Postgres وAuth وStorage وAPI مع ‌Envoy Gateway. دليل الترحيل من Kong إلى Envoy وإصلاح روابط S3.",11,"2026-04-21T00:00:00+00:00",{"id":20,"name":21,"slug":22,"color":23,"icon":24},[128],{"id":20,"name":21,"slug":22,"color":23,"icon":24},"\u002Fblog\u002Fcovers\u002Fheberger-supabase-vps-poster.svg",{"categorySlug":131,"appSlug":132},"قواعد-البيانات","supabase",{"id":134,"slug":135,"slugs":136,"title":140,"excerpt":141,"readTime":142,"views":16,"isPinned":17,"publishedAt":143,"category":144,"categories":145,"featuredImage":27,"bgImage":28,"posterImage":147,"relatedSolution":148},56,"postgresql-على-خادم-vps-قاعدة-بيانات-موثوقة-ومتحكم-بها",{"fr":137,"en":138,"ar":135,"es":139},"heberger-postgresql-vps","postgresql-on-a-vps-a-reliable-and-controlled-database","alojar-postgresql-en-un-vps","PostgreSQL على خادم VPS: قاعدة بيانات موثوقة ومُتحكَّم بها","استضف PostgreSQL على خادم VPS: وحدات التخزين والنسخ الاحتياطية والوصول الشبكي المحدود والإعداد السليم لتطبيقاتك.",4,"2026-04-25T00:00:00+00:00",{"id":20,"name":21,"slug":22,"color":23,"icon":24},[146],{"id":20,"name":21,"slug":22,"color":23,"icon":24},"\u002Fblog\u002Fcovers\u002Fheberger-postgresql-vps-poster.svg",{"categorySlug":131,"appSlug":149},"postgresql-stack",{"id":151,"slug":152,"slugs":153,"title":157,"excerpt":158,"readTime":159,"views":16,"isPinned":17,"publishedAt":160,"category":161,"categories":166,"featuredImage":27,"bgImage":28,"posterImage":168,"relatedSolution":27},282,"depends-on-لا-يكفي-healthcheck-لـ-postgresql-في-compose",{"fr":154,"en":155,"ar":152,"es":156},"docker-compose-depends-on-healthcheck","depends-on-is-not-enough-postgresql-healthcheck-in-compose","docker-compose-healthcheck-postgresql","depends_on لا يكفي: healthcheck لـ PostgreSQL في Compose","لماذا لا يضمن `depends_on` وحده جاهزية PostgreSQL، وكيف تُعدّ healthcheck موثوقاً باستخدام `service_healthy` لتجنب race conditions عند الإقلاع.",8,"2026-08-19T00:00:00+00:00",{"id":162,"name":163,"slug":164,"color":165,"icon":164},3,"النشر","deploiement","bg-success\u002F10 text-success",[167],{"id":162,"name":163,"slug":164,"color":165,"icon":164},"\u002Fblog\u002Fcovers\u002Fdocker-compose-depends-on-healthcheck-poster.svg",1788100067410]