تقدم هذه المقالة الصيغة المنشورة بواسطة PostgreSQL wiki لحساب التزامن المثالي لجهازك (صيغة تحجيم تجمع الاتصال الأكثر ذكرًا في النظام البيئي)، وتشرح سبب تكلفة كل اتصال أكثر من مؤشر ترابط التطبيق، ثم تشرح بالتفصيل الإجراء الخاص بتعيين الحد الأقصى للاتصالات دون تخمين. توثق منهجية المعيارية بروتوكول القياس المستخدم لأية مطالبات بالأداء في هذه المدونة.
الأساسيات
- بدون التجميع، يجب أن تغطي max_connections جميع اتصالات العميل المتزامنة، وليس فقط تلك التي يمكن لـ Postgres معالجتها بكفاءة بالتوازي.
- الصيغة المرجعية لـ PostgreSQL wiki: التزامن النشط المثالي = (النوى المادية × 2) + الأقراص الفعالة. نقطة بداية يجب التحقق من صحتها عن طريق القياس، وليس حدًا صارمًا.
- max_connections عبارة عن معلمة سياق
postmaster: يتطلب تغييرها إعادة تشغيل كاملة للخادم، وليس إعادة تحميل بسيطة. - كل اتصال Postgres عبارة عن عملية نظام منفصلة، وليس خيطًا خفيف الوزن: وهذا ما يجعل الحمل حقيقيًا بمجرد زيادة عدد الاتصالات.
- تم التحقق منه في الكود: في مجموعات Postgres المخصصة لها، تختلف Aurabase الحد الأقصى لعدد الاتصالات من 50 (الطبقة المجانية) إلى 400 (طبقة المؤسسة) اعتمادًا على حجم المجموعة.
لماذا يكلف اتصال Postgres أكثر من مؤشر ترابط التطبيق
لا يستخدم Postgres تجمع سلاسل رسائل خفيف الوزن لاتصالاته. يؤدي كل اتصال بالعميل إلى تشغيل عملية نظام كاملة.
تقوم عملية postmaster بإنشاء عملية جديدة ("شوكة") لكل محاولة اتصال، مخصصة لهذه الجلسة الفردية حتى يتم إغلاقها. تصف وثائق المشروع الرسمية هذه الآلية بدقة في الفصل الخاص بالأساسيات المعمارية (postgresql.org/docs/current/connect-estab.html، قسم "دلالات الاتصال"، تم الوصول إليه في 24 أغسطس 2026).
يتمتع هذا الاختيار بميزة حقيقية: أي تعطل أحد الاتصالات لا يؤثر على الاتصالات الأخرى، حيث يتم عزل كل عملية عن بقية الخادم. كما أن لها تكلفة مباشرة: فكل اتصال إضافي يضيف عملية نظام تشغيل كاملة للجدولة، مع مساحة الذاكرة الخاصة به وسياقه الخاص الذي يقوم بتبديل الحمل للنواة.
التطبيق الذي يفتح 500 اتصال مباشر بـ Postgres بدون تجميع يجبر الخادم على إدارة 500 عملية نظام متزامنة، حتى لو ظلت الغالبية العظمى منها خاملة بين طلبين.
ما يستهلكه الاتصال فعليًا: الذاكرة المشتركة وwork_mem
هناك آليتان مختلفتان تؤثران على الذاكرة، والخلط بينهما يؤدي دائمًا إلى تشخيص خاطئ.
الأول ثابت. عند بدء التشغيل، يحتفظ Postgres بهياكل الذاكرة المشتركة (الأقفال، جدول العمليات) بحجم قيمة max_connections، سواء تم فتح هذه الاتصالات لاحقًا أم لا. تشير الوثائق الرسمية للإعداد صراحةً إلى أن زيادته قد تتطلب ذاكرة مشتركة للنظام أكبر مما يسمح به التكوين الافتراضي لنظام التشغيل لديك (postgresql.org/docs/current/runtime-config-connection.html، تم الوصول إليه في 24 أغسطس 2026).
والثاني متغير، وأكثر خطورة على نطاق واسع: لا يتم تخصيص work_mem مرة واحدة لكل اتصال، ولكن مرة واحدة لكل عملية فرز أو تجزئة في خطة الاستعلام. الوثائق الرسمية واضحة بشأن هذه النقطة: يمكن للاستعلام المعقد إطلاق العديد من هذه العمليات بالتوازي، ويمكن لعدة جلسات أن تفعل الشيء نفسه في وقت واحد، بحيث يمكن أن تبلغ قيمة الذاكرة المستخدمة بالفعل عدة مرات Work_mem (postgresql.org/docs/current/runtime-config-resource.html، تم الوصول إليه في 24 أغسطس 2026).
ليست max_connections ×work_mem وحدها هي التي تهدد ذاكرة الخادم. إنه max_connections ×work_mem × عدد العمليات المتزامنة لكل استعلام. هذا المنتج هو الذي يشرح الخادم الذي يتم تبديله أو نفاد الذاكرة بعد زيادة الحد الأقصى للاتصالات التي تعتبر غير ضارة.
صيغة تحجيم ويكي PostgreSQL
يوثق ويكي مشروع PostgreSQL الرسمي صيغة مرجعية لحساب عدد اتصالات النشطة التي يمكن لجهازك معالجتها بكفاءة بالتوازي، وليس عدد الاتصالات المفتوحة إجمالاً (wiki.postgresql.org/wiki/Number_Of_Database_Connections، تم الوصول إليه في 24 أغسطس، 2026).
التزامن النشط المثالي = (النوى المادية × 2) + الأقراص الفعالة. عدد النوى لا يشمل فرط الترابط. يظل عدد الأقراص الفعالة قريبًا من 1 في وحدات تخزين SSD الحديثة، حيث تفقد فكرة وجود قرص فعلي منفصل ("المغزل") الكثير من معناها الأصلي.
على خادم يحتوي على 8 مراكز فعلية ومخزن SSD، تعطي الصيغة (8 × 2) + 1 = 17 اتصالًا نشطًا قبل أن يبدأ معدل النقل في الانخفاض. غالبًا ما يكون هذا الرقم مفاجئًا: فهو يبدو صغيرًا مقارنة بمئات الاتصالات التي يفتحها التطبيق عمليًا. وهذا هو بالضبط موضوع الفقرة التالية.
يقيس الرقم المحسوب بواسطة الصيغة التزامن الذي يمكن لوحدة المعالجة المركزية والقرص استيعابه، وليس عدد اتصالات العميل التي يحتاج التطبيق الخاص بك إلى فتحها. يفتح أسطول مكون من 20 عملية تطبيق، كل منها بمجموعتها الخاصة المكونة من 10 اتصالات، 200 اتصال متزامن لـ Postgres حتى لو كان 17 منها فقط تعمل بنشاط في أي وقت محدد. بدون مُجمِّع، يجب أن تغطي max_connections 200، وليس 17. هذه الفجوة هي التي تدفع معظم المعماريات لإضافة مُجمِّع في وضع المعاملة، حتى لو كان ذلك يعني اختيار أي منها (راجع مقارنة PgBouncer وSupavisor وPgCat).
كيفية تغيير max_connections (ولماذا يلزم إعادة التشغيل)
لم يتم تبديل max_connections بشكل سريع. هذه معلمة سياق postmaster: يقرأها Postgres مرة واحدة، عند بدء التشغيل، لتحديد حجم الذاكرة المشتركة الخاصة به. إعادة تحميل التكوين (pg_reload_conf() أو SIGHUP) ليست كافية، يجب عليك إعادة تشغيل الخادم.
تحقق أولاً من القيمة الحالية وسياقها للتأكد من أن إعادة التشغيل ستكون ضرورية:
ثم قم بتطبيق القيمة الجديدة، ثم أعد التشغيل:
يتضمن max_connections افتراضيًا superuser_reserved_connections (3 افتراضيًا): هذه الاتصالات محجوزة للمستخدم المتميز في حالة التشبع، ولن تكون متاحة أبدًا لتطبيقك، حتى لو لم يتم الوصول إلى العداد العام بعد.
كيف تقوم Aurabase بميزانية max_connections على مجموعات Postgres الخاصة بها
إن تحديد حجم max_connections ليس مجرد تمرين نظري. إليك كيفية قيام Aurabase بتخصيصها لمجموعات Postgres المُدارة:
مجموعات مخصصة: مجموعة Postgres واحدة لكل مشروع
على هذا المستوى (راجع مقارنتنا المخصصة مقابل القاعدة المشتركة)، يتلقى كل مشروع مجموعة CloudNativePG الخاصة به وميزانية max_connections الخاصة به، والتي تتناسب مع حجم المثيل:
| مجاني (مخصص) | الحد الأقصى لعدد الاتصالات 50 | مثيل واحد · 500 متر من وحدة المعالجة المركزية الافتراضية · 512 ميجا |
|---|---|---|
| الموالية (الافتراضي) | الحد الأقصى للاتصالات 200 | حالتان · وحدة معالجة مركزية افتراضية واحدة · 2Gi |
| فريق | الحد الأقصى للاتصالات 300 | 3 حالات · 2 وحدة معالجة مركزية افتراضية · 3Gi |
| عمل | الحد الأقصى للاتصالات 400 | 3 حالات · 2 وحدة معالجة مركزية افتراضية · 4Gi |
المجموعات المشتركة: عدة مشاريع لمنظمة ما، وميزانية مشتركة
في هذا المسار الثاني، تتصل جميع مشاريع نفس المؤسسة عبر مجمع CNPG (وضع PgBouncer، transaction) أمام ملف أساسي مشترك:
| مجانا | الحد الأقصى لعدد الاتصالات 50 | max_client_conn 100 | الحد الأقصى_لاتصالات_المستخدمين 20 |
|---|---|---|---|
| الموالية | الحد الأقصى لعدد الاتصالات 100 | max_client_conn 200 | الحد الأقصى_لاتصالات_المستخدمين 60 |
| فريق | الحد الأقصى للاتصالات 200 | max_client_conn 400 | الحد الأقصى_لاتصالات_المستخدمين 150 |
تتصل جميع المشاريع في المؤسسة من خلال دور تطبيق مشترك. لذلك، فإن max_user_connections وحده يحدد إجمالي اتصالات الخادم التي يمكن لهذا الدور فتحها عبر المجموعة بأكملها: هذه هي الحماية الحقيقية للمجموعة العالمية، وليس max_client_conn، الذي يحد فقط من اتصالات العميل بالمجمع نفسه.
ومع ذلك، لا يخدم هذا المجمع سوى حركة مرور تطبيقات SDK. يظل PostgREST، من جانبه، متصلاً مباشرة بالخدمة الأساسية (-rw): سيؤدي التجميع في وضع المعاملة إلى كسر آلية إعادة تحميل المخطط الخاصة به، والتي تستمع إلى قناة LISTEN مخصصة تسمى pgrst. وبالتالي، فإن اتصالاتها الخاصة (2 لكل نسخة متماثلة على المستوى المشترك، و10 لكل نسخة متماثلة على المستوى المخصص) يتم احتسابها مباشرة في ميزانية max_connections الأساسية، خارج أي مجمع، وهو بالضبط نوع الاتصال "المنسي" الذي يجب أن تتضمنه الخطوة 1 من الإجراء أدناه.
يوثق الكود بوضوح ميزانيات المجمع المشتركة هذه كقيم أولية يجب معايرتها في ظروف حقيقية، عن طريق قياس pg_stat_activity تحت الحمل، وليس كأرقام ثابتة من معيار منشور. هذا هو نفس النظام الموضح في منهجية قياس الأداء : القياس قبل التعديل، وليس التخمين ثم الأمل. تعمل هذه المجموعات على PostgreSQL 16، وهو خيار موثق في مقارنة Postgres 16 vs 17 vs 18.
الإجراء المكون من 5 خطوات لتحديد حجم الحد الأقصى للاتصالات دون التجميع
لا يعتمد هذا الإجراء على أي أداة معينة: فهو ينطبق على أي خادم Postgres، مُدارًا أو مستضافًا ذاتيًا.
- قم بإحصاء اتصالات العميل الفعلية. عدد عمليات التطبيق مضروبًا في حجم مجموعتها الداخلية، بالإضافة إلى أدوات الإدارة والنسخ والمراقبة. هذا الرقم، وليس الصيغة، هو الذي يحدد الحد الأقصى للاتصالات.
- احسب التزامن المثالي لجهازك باستخدام الصيغة من PostgreSQL wiki: (النوى المادية × 2) + الأقراص الفعالة. يشير هذا الشكل إلى عدد هذه الاتصالات التي يمكن أن تعمل فعليًا بالتوازي دون انخفاض الإنتاجية.
- قم بتعيين max_connections فوق الحاجة الفعلية للخطوة 1، مع هامش لـ
superuser_reserved_connectionsولأي أدوات إدارية تفتح اتصالاتها الخاصة خارج التطبيق. - قم بتطبيق التغيير باستخدام ALTER SYSTEM SET، ثم أعد تشغيل الخادم. هذه معلمة مدير مكتب البريد: إعادة التحميل البسيطة ليست كافية، كما هو مفصل أعلاه.
- مراقبة pg_stat_activity مع مرور الوقت. إذا كان عدد الاتصالات الخاملة يتجاوز عدد الاتصالات النشطة بشكل كبير، فهذه ليست مشكلة max_connections: إنها إشارة إلى أنك بحاجة إلى مُجمّع أمام الخادم، وليس رقمًا أعلى.
طلب المراقبة من الخطوة 5، قابل للاستخدام مباشرة:
عندما لا تكون الصيغة كافية: العلامات التي تشير إلى حاجتك إلى أداة تجميع
يتم إرجاع ثلاث إشارات بشكل منهجي عندما لا تعد max_connections وحدها كافية، مهما كانت قيمتها.
- يظهر الخطأ
FATAL: sorry, too many clients alreadyأثناء التحميل الأقصى، بينما تكون غالبية الاتصالات المعروضة بواسطةpg_stat_activityفي حالة الخمول. - يعمل التطبيق في بيئة بدون خادم أو مع عمال سريعين (وظائف الحافة، المهام القصيرة)، والتي تفتح وتغلق الاتصالات بشكل أسرع بكثير من نموذج العملية لكل اتصال الذي صممه Postgres لاستيعابه.
- لقد تم بالفعل تطبيق الصيغة والإجراء أعلاه، وتستمر الحاجة الفعلية لاتصالات العميل في تجاوز ما يمكن تخصيصه من الذاكرة المتاحة دون تعريض ذاكرة العمل أو المخزن المؤقت المشترك للخطر.
في هذه الحالات الثلاث، تكون الإجابة الصحيحة دائمًا تقريبًا عبارة عن مُجمِّع متوضع بين التطبيق وPostgres، وليس الحد الأقصى للاتصالات. لدينا مقارنة PgBouncer وSupavisor وPgCat توضح بالتفصيل الخيارات الثلاثة، ويشرح دليل الخاص بنا لوضع المعاملة التسوية الأكثر شيوعًا بمجرد وضع المجمع في مكانه الصحيح. بالنسبة لجميع عمليات ضبط Postgres خارج نطاق الاتصالات، راجع قائمة التحقق من ضبط Postgres للإنتاج .