دليل عملي

هجرة SQL Server 2016 إلى PostgreSQL على VPS

قواعد البيانات12 دقيقةً للقراءةعدد الخطوات: 8

‏في 14 يوليو 2026، أنهت ‏Microsoft دعمها الممتد لـ ‏SQL Server 2016. لن تصدر أي تحديثات أمنية لهذا الإصدار بعد الآن. أمام الفرق التي لا تزال تعمل على هذه القاعدة خياران واقعيان: الترقية المدفوعة إلى ‏SQL Server 2022، أو الهجرة إلى بديل مفتوح المصدر. ‏PostgreSQL 16 قاعدة بيانات علائقية ناضجة وعالية الأداء ولا تكلف رسوم ترخيص. الهجرة ليست بسيطة — فلهجة ‏T-SQL الخاصة بـ ‏Microsoft اختلافات جوهرية عن ‏SQL المعياري، كما تختلف أنواع البيانات في نقاط عدة. يوضح هذا الدليل التعارضات الجوهرية، ومقابلات الأنواع، وخطة تبديل منظمة لتجنب فقدان البيانات والانحدار في أداء التطبيق.

المحتويات· ‏SQL Server 2016‏: نهاية الدعم الممتد في 14 يوليو 20261/11
  1. 01‏SQL Server 2016‏: نهاية الدعم الممتد في 14 يوليو 2026
  2. 02لماذا نختار PostgreSQL بدلاً من ترقية SQL Server أو Azure SQL
  3. 03التدقيق الأولي: ما يُهاجَر بسلاسة وما يستلزم عملاً
  4. 04مقابلة أنواع البيانات: SQL Server ← PostgreSQL
  5. 05تعارضات T-SQL الشائعة ومقابلاتها في PostgreSQL
  6. 06خطة الهجرة في 8 خطوات
  7. 07ضبط PostgreSQL 16 على VPS للإنتاج
  8. 08المزالق: الإجراءات المخزنة ومحفزات T-SQL
  9. 09اختبار الحمل قبل التبديل: pgbench ومقارنة خطط الاستعلام
  10. 10استكشاف الأخطاء — الأخطاء الشائعة في هجرة SQL Server إلى PostgreSQL
  11. 11التحقق من الهجرة وإعادة الوصول للمستخدمين

‏SQL Server 2016‏: نهاية الدعم الممتد في 14 يوليو 2026

‏تنص سياسة دورة الحياة لدى ‏Microsoft على عشر سنوات من الدعم لكل إصدار من ‏SQL Server‏: خمس سنوات دعم عادي ثم خمس سنوات دعم ممتد. بالنسبة لـ ‏SQL Server 2016، انتهى الدعم الممتد في 14 يوليو 2026. بعد هذا التاريخ، لا تُصدر ‏Microsoft أي تحديثات أمنية أو إصلاحات حرجة لهذا الإصدار. يتراكم على أي خادم ‏SQL Server 2016 متصل بالشبكة بعد هذا التاريخ ثغرات أمنية غير مسدودة. تشترط المتطلبات التنظيمية — ‏PCI-DSS‏ و‏GDPR‏ و‏ISO 27001 — عموماً أن تتلقى مكونات البنية التحتية التحديثات الأمنية المتاحة. وبالتالي فإن الاستمرار على ‏SQL Server 2016 بعد يوليو 2026 يُعدّ انحرافاً موثقاً قابلاً للرصد في أي تدقيق.

لماذا نختار PostgreSQL بدلاً من ترقية SQL Server أو Azure SQL

  • ‏تكلفة ترخيص صفرية: ‏PostgreSQL صادر بموجب رخصة ‏PostgreSQL (مرنة تشبه ‏BSD)، دون ‏CAL ودون إصدار ‏Enterprise منفصل للشراء.
  • ‏تحكم كامل في البنية التحتية: على ‏VPS مخصص، تتولى إدارة الإصدارات والإضافات وضبط الذاكرة والنسخ الاحتياطية دون الاعتماد على مزود سحابي.
  • ‏SQL Server 2022 يُعالج ثقل الإصدار لكنه يُبقي تكاليف الترخيص ويربط المؤسسة بمنظومة ‏Microsoft.
  • ‏Azure SQL Managed Instance يبسّط الهجرة لكنه يُضيف تكلفة شهرية متكررة وتبعية لـ ‏Azure وقيوداً إضافية على الشبكة.
  • ‏PostgreSQL يدعم الميزات المتقدمة ذاتها: دوال النوافذ التحليلية، ‏CTE المتكررة، ‏JSON الأصيل، تقسيم الجداول، والنسخ المتماثل المنطقي.
  • ‏منظومة الأدوات واسعة: ‏pgAdmin وDBeaver وMetabase وPostgREST، ومعظم أطر ‏ORM (‏Entity Framework وHibernate وSQLAlchemy وActiveRecord) تدعم ‏PostgreSQL.
  • ‏توزيعات ‏Linux الرئيسية تحزّم ‏PostgreSQL مع تحديثات أمنية منتظمة ضمن عقد صيانة التوزيعة.

التدقيق الأولي: ما يُهاجَر بسلاسة وما يستلزم عملاً

‏قبل كتابة أي أمر للهجرة، لا بد من تدقيق الهيكل. العناصر التي تُهاجَر دون عائق: الجداول البسيطة ذات الأنواع المعيارية، وقيود ‏PRIMARY KEY وFOREIGN KEY وUNIQUE وNOT NULL، والمؤشرات من نوع ‏B-tree، والعروض الخالية من صياغة ‏T-SQL الخاصة، والتسلسلات. العناصر التي تستلزم عملاً صريحاً: الإجراءات المخزنة ودوال ‏T-SQL (صياغة غير متوافقة، يجب إعادة كتابتها بـ ‏PL/pgSQL أو نقلها إلى طبقة التطبيق)، والمحفزات التي تستخدم الجداول الوهمية ‏INSERTED وDELETED (المقابل في ‏PostgreSQL‏: ‏NEW وOLD)، وأعمدة ‏ROWVERSION/TIMESTAMP المستخدمة لاكتشاف التزامن التفاؤلي، والأعمدة المحسوبة، وتلميحات القفل (‏WITH (NOLOCK) و‏WITH (UPDLOCK))، والجداول المؤقتة العامة (‏##temp). يمكن الحصول على قائمة كاملة بعناصر ‏SQL Server عبر استعلام ‏INFORMATION_SCHEMA وعروض النظام ‏sys‎.objects وsys‎.procedures وsys‎.triggers.

مقابلة أنواع البيانات: SQL Server ← PostgreSQL

مرّر الجدول أفقيًا

نوع SQL Serverنوع PostgreSQLملاحظة
DATETIME2TIMESTAMPTZ‏تخزين الطوابع الزمنية مع المنطقة الزمنية؛ ‏DATETIME2 لا يحمل منطقة زمنية، يجب تحديد اتفاقية ‏UTC صراحةً
UNIQUEIDENTIFIERUUID‏PostgreSQL يدعم ‏UUID أصلياً؛ استخدم إضافة ‏uuid-ossp أو ‏gen_random_uuid()‎ للتوليد
NVARCHAR(MAX) / NTEXTTEXT‏PostgreSQL يخزّن جميع السلاسل بـ ‏UTF-8؛ لا تمييز بين ‏NVARCHAR وVARCHAR ولا حد ‏MAX منفصل
BITBOOLEAN‏تصبح القيم ‏0/1 قيمتَي ‏false/true؛ انتبه لأعمدة ‏BIT المستخدمة كأعداد صحيحة في العمليات الحسابية
MONEY / SMALLMONEYNUMERIC(19,4)‏MONEY في ‏SQL Server عدد صحيح مُدرَّج، ‏NUMERIC دقيق؛ سلوك متطابق للحسابات المالية
INT IDENTITY(1,1)SERIAL أو GENERATED ALWAYS AS IDENTITY‏SERIAL اختصار لتسلسل؛ ‏GENERATED ALWAYS AS IDENTITY معيار ‏SQL:2003، يُفضَّل للجداول الجديدة
ROWVERSION / TIMESTAMPbytea + trigger أو xmin‏لا مقابل مباشر؛ عمود النظام ‏xmin يُعالج اكتشاف التزامن التفاؤلي في معظم الحالات

تعارضات T-SQL الشائعة ومقابلاتها في PostgreSQL

‏ثمة بنى ‏T-SQL شائعة لا مقابل مباشر لها في ‏SQL المعياري وتستلزم إعادة كتابة.

‏TOP N بدون ORDER BY‏: يقبل ‏SQL Server ‏SELECT TOP 10 * FROM t بلا ترتيب. يستلزم ‏PostgreSQL استخدام ‏LIMIT 10؛ وإن كان الترتيب مهماً فأضف ‏ORDER BY صريحاً.

‏ISNULL(expr, value)‏: تقابلها الدالة المعيارية ‏COALESCE(expr, value). السلوك متطابق للحالات الشائعة.

‏GETDATE()‎ و‏GETUTCDATE()‎‏: تصبحان ‏NOW()‎ (طابع زمني مع منطقة الجلسة) و‏NOW() AT TIME ZONE 'UTC'‎ أو ‏CURRENT_TIMESTAMP على التوالي.

‏DATEDIFF و‏DATEADD‏: يستخدم ‏PostgreSQL حساب الفترات: ‏date + INTERVAL '7 days'‎، ويُرجع ‏date2 - date1 قيمة ‏INTERVAL.

‏تلميح ‏WITH (NOLOCK)‏: يطلب هذا التلميح قراءة بلا قفل مشترك. لا يدعم ‏PostgreSQL هذا التلميح؛ يغطي مستوى عزل ‏READ COMMITTED (الافتراضي) معظم حالات الاستخدام. لتقارير التحليل التي تتحمل بيانات قديمة قليلاً، النسخة المتماثلة للقراءة هي الحل البنيوي.

‏PRINT في الإجراءات: استخدم ‏RAISE NOTICE 'message'‎ في ‏PL/pgSQL.

‏GO كفاصل دُفعات: لا وجود لهذا الفاصل في ‏PostgreSQL؛ يجب إعادة هيكلة السكريبتات إلى معاملات أو كتل ‏DO $$...$$‎ منفصلة.

خطة الهجرة في 8 خطوات

  1. ‏حصر الهيكل وتدقيقه: تصدير قائمة بجميع الجداول والأعمدة مع أنواعها والمؤشرات والقيود والإجراءات المخزنة والدوال والمحفزات والعروض. تحديد الكائنات التي تستلزم إعادة كتابة يدوية وترتيبها حسب الأولوية.

  2. ‏إعداد خادم ‏PostgreSQL المستهدف على ‏VPS‏: تثبيت ‏PostgreSQL 16، وضبط ‏postgresql‎.conf (الذاكرة المشتركة، الاتصالات، ‏WAL)، وإنشاء مستخدم التطبيق بالحد الأدنى من الصلاحيات، وتفعيل ‏TLS للاتصالات البعيدة.

  3. ‏تحويل الهيكل والبيانات باستخدام ‏pgloader أو يدوياً: يُهاجر الأمر ‏pgloader mssql://user:pass@host/db postgresql://user:pass@vps/db‎ الهيكل والبيانات بأمر واحد. للهياكل المعقدة، صدّر ‏DDL من ‏SQL Server وكيّفه يدوياً مستعيناً بجدول مقابلة الأنواع.

  4. ‏التحقق من الهيكل المُهاجَر: التحقق من عدد الجداول وعدد الصفوف لكل جدول والنزاهة المرجعية (‏FOREIGN KEY) والمؤشرات. مقارنة الأنواع الفعلية بالأنواع المتوقعة عبر ‏information_schema‎.columns.

  5. ‏إعادة كتابة الإجراءات المخزنة والمحفزات: يجب إعادة كتابة كل كائن ‏T-SQL بـ ‏PL/pgSQL أو نقل منطقه إلى طبقة التطبيق. اختبار كل إجراء بشكل مستقل بمجموعات بيانات تمثيلية.

  6. ‏تكييف كود التطبيق: البحث في الكود المصدري عن جميع عبارات ‏SQL الحرفية والاستعلامات ذات المعاملات التي تستخدم بنى ‏T-SQL الخاصة. تحديث موصّل الاتصال (التحول من ‏mssql إلى ‏pg أو ‏psycopg2 أو ‏npgsql أو الموصّل المناسب للبنية التقنية).

  7. ‏اختبار الحمل والتراجع: تشغيل مجموعة اختبارات التراجع الكاملة على قاعدة بيانات ‏PostgreSQL للتجهيز. استخدام ‏pgbench للتحقق من الأداء تحت الضغط. مقارنة خطط تنفيذ الاستعلامات الحرجة (‏EXPLAIN ANALYZE) بين ‏SQL Server وPostgreSQL.

  8. ‏التبديل في نافذة صيانة: تحديد نافذة زمنية (ليلاً أو عطلة نهاية الأسبوع)، وضع التطبيق في وضع الصيانة، تشغيل هجرة تفاضلية نهائية للبيانات المضافة منذ الهجرة الأولية، توجيه ‏DSN التطبيق نحو ‏PostgreSQL، التحقق من الوظائف الحرجة، ورفع الصيانة. إبقاء ‏SQL Server في وضع القراءة فقط 48 ساعة للسماح بتراجع سريع عند الحاجة.

ضبط PostgreSQL 16 على VPS للإنتاج

‏التثبيت الافتراضي لـ ‏PostgreSQL غير مضبوط للإنتاج. المعاملات التالية في ‏postgresql‎.conf هي نقطة انطلاق لـ ‏VPS بذاكرة 4 ‏GB.

‏shared_buffers‏: اضبطها على 25% من الذاكرة المتاحة، أي ‏1GB لـ 4 ‏GB. يحدد هذا المعامل الذاكرة المخصصة للذاكرة المؤقتة الداخلية لـ ‏PostgreSQL.

‏effective_cache_size‏: اضبطها على 75% من إجمالي الذاكرة، أي ‏3GB. يُعلم هذا المعامل مُخطِّط الاستعلامات بالذاكرة المتاحة لذاكرة نظام التشغيل المؤقتة.

‏work_mem‏: من ‏16MB إلى ‏64MB حسب تعقيد استعلامات الترتيب. يُطبَّق هذا المعامل لكل عملية ترتيب ولكل اتصال؛ قيمة مرتفعة جداً على خادم يحمل اتصالات متزامنة كثيرة تُنهك الذاكرة.

‏maintenance_work_mem‏: ‏256MB لعمليات الصيانة (‏VACUUM وCREATE INDEX).

‏max_connections‏: ‏100 كافٍ لمعظم التطبيقات التي تستخدم مجمّع اتصالات. إن كان التطبيق يفتح اتصالاً لكل طلب بلا مجمّع، استخدم ‏PgBouncer أمامه.

‏في ‏pg_hba‎.conf‏، اقصر الاتصالات البعيدة على عنوان ‏IP خادم التطبيق واشترط ‏TLS‏: ‏hostssl all appuser 10.0.0.5/32 scram-sha-256.

‏فعّل ‏TLS بتوليد شهادة (‏Let's Encrypt أو شهادة داخلية) وضبط ‏ssl = on وssl_cert_file وssl_key_file في ‏postgresql‎.conf.

المزالق: الإجراءات المخزنة ومحفزات T-SQL

‏الإجراءات المخزنة بـ ‏T-SQL هي نقطة الاحتكاك الرئيسية في الهجرة من ‏SQL Server إلى ‏PostgreSQL. ‏T-SQL لهجة خاصة بهياكل تحكم ومعالجة مؤشرات ومعالجة أخطاء (كتل ‏TRY..‎.CATCH) لا مقابل مباشر لها في ‏PL/pgSQL.

‏مؤشرات ‏FAST_FORWARD في ‏SQL Server تصبح حلقات ‏FOR في ‏PL/pgSQL، لكن الأداء مماثل ويجب في كل الأحوال التساؤل عن ضرورة المؤشرات: الاستعلام المبني على مجموعات البيانات يحل محل المؤشر بشكل أكثر كفاءة في الغالب.

‏كتلة ‏TRY..‎.CATCH تصبح ‏BEGIN..‎.EXCEPTION WHEN OTHERS THEN في ‏PL/pgSQL.

‏الجداول المؤقتة المحلية (‏#temp) تقابلها الجداول المؤقتة للجلسة في ‏PostgreSQL المنشأة بـ ‏CREATE TEMPORARY TABLE. الجداول المؤقتة العامة (‏##temp) لا مقابل مباشر لها — يجب استبدالها بجداول دائمة مع إدارة صريحة لدورة الحياة.

‏المحفزات التي تُشير إلى ‏INSERTED وDELETED (الجداول الوهمية في ‏SQL Server) يجب إعادة كتابتها لاستخدام ‏NEW وOLD في ‏PostgreSQL. هيكل التشغيل يختلف أيضاً: يُميز ‏PostgreSQL بين محفزات ‏BEFORE وAFTER، وبين ‏FOR EACH ROW وFOR EACH STATEMENT.

‏نهج عملي يقضي بنقل منطق الإجراءات المخزنة إلى طبقة التطبيق أثناء الهجرة، مما يبسّط الاختبار ويقلل الارتباط بين التطبيق وقاعدة البيانات.

اختبار الحمل قبل التبديل: pgbench ومقارنة خطط الاستعلام

‏قبل التبديل للإنتاج، تحقق من الأداء باستخدام ‏pgbench. تهيئة قاعدة بيانات اختبار تمثيلية: ‏pgbench -i -s 50 db_name‎ ينشئ هيكل معياري بخمسة ملايين صف. شغّل محاكاة حمل: ‏pgbench -c 20 -j 4 -T 60 db_name‎ يحاكي 20 اتصالاً متوازياً لمدة 60 ثانية ويُبلّغ بالمعاملات في الثانية. للاستعلامات الحرجة في التطبيق، قارن خطط التنفيذ بين ‏SQL Server (‏SET STATISTICS IO ON; SELECT ...‎) و‏PostgreSQL (‏EXPLAIN (ANALYZE, BUFFERS) SELECT ...‎). راقب مسح الجداول الكاملة غير المتوقعة (مؤشر مفقود أو إحصائيات غير محسوبة — شغّل ‏ANALYZE بعد الهجرة) وصلات ‏NESTED LOOP على أحجام كبيرة ستستفيد من ‏HASH JOIN. حدّث الإحصائيات بعد الهجرة الأولية بـ ‏ANALYZE table_name أو ‏VACUUM ANALYZE على قاعدة البيانات كاملة.

استكشاف الأخطاء — الأخطاء الشائعة في هجرة SQL Server إلى PostgreSQL

‏ثمة فئات من الأخطاء تتكرر بانتظام في الهجرات الأولى.

‏ERROR: column is of type uuid but expression is of type character varying‏: عمود ‏UNIQUEIDENTIFIER مُهاجَر إلى ‏UUID يتلقى سلسلة بتنسيق ‏UUID بلا تحويل صريح. كيّف استعلام التطبيق ليُرسل نوع ‏UUID حقيقياً، أو أضف تحويلاً ضمنياً في ‏PostgreSQL (‏CREATE CAST)، أو هاجر العمود إلى ‏TEXT إن لم تُستغل دلالات ‏UUID.

‏ERROR: operator does not exist: boolean = integer‏: عمود ‏BIT مُهاجَر إلى ‏BOOLEAN يُقارَن بـ ‏0 أو ‏1. استبدل ‏col = 1 بـ ‏col = true أو ببساطة ‏col في جمل ‏WHERE.

‏ERROR: function isnull(character varying, text) does not exist‏: استبدل جميع استدعاءات ‏ISNULL بـ ‏COALESCE.

‏ERROR: syntax error at or near "TOP"‏: صياغة ‏SELECT TOP N غير موجودة في ‏PostgreSQL. استبدلها بـ ‏SELECT ... LIMIT N.

‏تجاوزات صامتة على أعمدة ‏MONEY ← NUMERIC‏: تحقق من أن القيم القصوى في الجدول المصدر تتسع ضمن الدقة المستهدفة ‏NUMERIC(19,4). نطاق ‏MONEY في ‏SQL Server هو ‏±922,337,203,685,477.5807؛ يغطي ‏NUMERIC(19,4) النطاق ‏±999,999,999,999,999.9999، وهو كافٍ في جميع الحالات تقريباً.

‏فقدان بيانات على أعمدة ‏DATETIME بلا منطقة زمنية: ‏DATETIME وDATETIME2 في ‏SQL Server لا يخزنان المنطقة الزمنية. إن كانت قاعدة البيانات تُغذَّى من تطبيقات في مناطق زمنية متعددة، ستُفسَّر الطوابع الزمنية المُهاجَرة إلى ‏TIMESTAMPTZ بلا تحويل سابق على أنها ‏UTC. حدد اتفاقية (‏UTC أو التوقيت المحلي) وطبّق تحويل ‏AT TIME ZONE أثناء الهجرة إن لزم.

التحقق من الهجرة وإعادة الوصول للمستخدمين

‏بعد التبديل، تُقلل قائمة التحقق المنظمة من خطر إعادة المستخدمين إلى قاعدة بيانات ناقصة.

‏تحقق من عدد الصفوف لجميع الجداول الحرجة: استعلام على ‏information_schema‎.tables مع ‏COUNT(*)‎ لكل جدول، مقارنةً بالأرقام المسجلة من ‏SQL Server قبل الهجرة.

‏تحقق من النزاهة المرجعية: ‏SELECT * FROM pg_constraint WHERE contype = 'f'‎ يُدرج جميع قيود المفتاح الخارجي؛ حاول إدراجاً ينتهك قيداً للتأكد من فعاليتها.

‏تحقق من المؤشرات: ‏SELECT indexname, indexdef FROM pg_indexes WHERE schemaname = 'public'‎ يُدرج جميع المؤشرات المنشأة. قارنها بقائمة مؤشرات ‏SQL Server.

‏اختبر الوظائف الحرجة في التطبيق: مسار الشراء، والمصادقة، والتقارير، والتصدير — على الأقل المسارات التي تمس الجداول الأكثر حجماً والاستعلامات الأكثر تعقيداً.

‏راقب سجلات ‏PostgreSQL خلال الـ 24 ساعة الأولى: ‏tail -f /var/log/postgresql/postgresql-*‎.log‎. تظهر أخطاء عدم تطابق الأنواع ومهلات الاتصال وخطط الاستعلام دون المستوى الأمثل عادةً في الساعات الأولى من حركة المرور الحقيقية.

‏أبق ‏SQL Server في وضع القراءة فقط 48 ساعة مع تقييد الوصول للفريق التقني. التراجع يعني توجيه ‏DSN التطبيق مجدداً نحو ‏SQL Server وإعادة تشغيل البيانات المكتوبة في ‏PostgreSQL خلال نافذة التبديل.

VPS جاهز لـ PostgreSQL 16

‏VPS من ‏ServOrbit مهيأة لـ ‏PostgreSQL 16‏: أقراص ‏NVMe SSD، لقطة يومية، وصول ‏root كامل. انشر قاعدة بياناتك المُهاجَرة بلا قيود ترخيص.

بحاجة إلى مساعدة؟

تصفّح مركز المساعدة والأسئلة الشائعة، أو تواصل مع فريقنا — معاودة اتصال أو WhatsApp أو بريد إلكتروني. الدعم بـالعربية والفرنسية والإنجليزية.

راسلنا على WhatsAppيُفتح في علامة تبويب جديدة