خيارات نموذج بيانات SaaS متعدد المستأجرين لباكند بلا كود
خيارات نموذج بيانات SaaS متعدد المستأجرين تؤثر على الأمان والتقارير والأداء. قارن tenant_id، المخططات المنفصلة، وقواعد البيانات المنفصلة مع توضيح المقايضات.

المشكلة: الحفاظ على فصل المستأجرين دون إبطاء النظام
تعني تعددية المستأجرين أن منتج برمجي واحد يخدم عملاء كثيرين (مستأجرين)، ويجب أن يرى كل مستأجر بياناته فقط. الصعوبة هي تنفيذ ذلك باستمرار: ليس في شاشة واحدة فقط، بل عبر كل استدعاء API، لوحة إدارة، تصدير، ومهمة خلفية.
نموذج البيانات يؤثر على العمليات اليومية أكثر مما تتوقع الفرق عادةً. فهو يشكل الصلاحيات، التقارير، سرعة الاستعلام مع النمو، ومدى خطورة "خطأ صغير". إغفال فلتر واحد قد يسرّب بيانات. العزل المبالغ فيه يجعل التقارير عبئًا.
هناك ثلاث طرق شائعة لتنظيم نموذج بيانات SaaS متعدد المستأجرين:
- قاعدة بيانات واحدة حيث يحتوي كل جدول على
tenant_id - مخططات منفصلة لكل مستأجر داخل قاعدة بيانات واحدة
- قواعد بيانات منفصلة لكل مستأجر
حتى عند البناء بصريًا في باكند بلا كود، تطبق نفس المقايضات. أدوات مثل AppMaster تولّد كود باكند وهياكل قواعد بيانات حقيقية من تصميمك، لذا تظهر قرارات النمذجة المبكرة بسرعة في سلوك الإنتاج والأداء.
تخيل أداة دعم. إذا كان كل صف تذكرة يحوي tenant_id، فمن السهل الاستعلام عن "كل التذاكر المفتوحة"، لكن يجب فرض فحوصات المستأجر في كل مكان. إذا كان لكل مستأجر مخطط أو قاعدة بيانات منفصلة، يصبح العزل أقوى بشكل افتراضي، لكن تقارير عبر المستأجرين (مثل "متوسط وقت الإغلاق لجميع العملاء") تتطلب عملًا إضافيًا.
الهدف هو فصل يمكنك الوثوق به دون إضافة احتكاك للتقارير، الدعم، والنمو.
طريقة سريعة للاختيار: 4 أسئلة تحدد الخيار
لا تبدأ بنظرية قواعد البيانات. ابدأ بكيفية استخدام المنتج وما تحتاجه لتشغيله أسبوعيًا.
أربعة أسئلة تجعل الجواب واضحًا عادةً
-
ما مدى حساسية البيانات وهل أنتم تحت قواعد صارمة؟ الرعاية الصحية، المالية، والعقود الصارمة غالبًا تدفع نحو عزل أقوى (مخطط منفصل أو قاعدة بيانات منفصلة). يمكن أن يقلل ذلك المخاطر ويسهّل التدقيق.
-
هل تحتاج تقارير عبر المستأجرين بشكل متكرر؟ إذا احتجت بانتظام مؤشرات "كل العملاء" (استخدام، إيرادات، أداء)، فقاعدة بيانات واحدة مع
tenant_idعادة أبسط. قواعد البيانات المنفصلة تجعل ذلك أصعب لأنك تحتاج الاستعلام من أماكن متعددة ودمج النتائج. -
إلى أي مدى سيختلف المستأجرون عن بعضهم؟ إن احتاج المستأجرون حقولًا مخصصة أو سير عمل فريد أو تكاملات خاصة، قد تقلل المخططات أو قواعد البيانات المنفصلة فرص تسرب التغييرات. إذا كان معظم المستأجرين يشتركون في نفس البنية، يبقى
tenant_idنظيفًا. -
ماذا يستطيع فريقك تشغيل عمليًا؟ العزل الأكبر عادةً يعني عملًا أكثر: نسخًا احتياطية متعددة، ترحيلات أكثر، أجزاء متحركة أكثر، ومزيدًا من أماكن احتمالية الأخطاء.
نهج عملي هو نمذجة خيارين علويين ثم اختبار نقاط الألم الحقيقية: قواعد الصلاحيات، استعلامات التقارير، وكيف تنتشر التغييرات مع تطور النموذج.
النهج 1: قاعدة بيانات واحدة مع tenant_id في كل صف
هذا هو الإعداد الأكثر شيوعًا: كل العملاء يشتركون في نفس الجداول، ويحمل كل سجل مملوك لمستأجر عمود tenant_id. إنه بسيط تشغيليًا لأنك تدير قاعدة بيانات واحدة ومجموعة واحدة من الترحيلات.
القاعدة صارمة: إن كان الصف يخص مستأجرًا، فيجب أن يتضمن tenant_id، ويجب أن تقوم كل استعلام بترشيحه. عادةً تشمل الجداول المملوكة للمستأجر المستخدمين، الأدوار، المشاريع، التذاكر، الفواتير، الرسائل، بيانات الملفات، وجداول الربط.
لتقليل التسريبات، عامل tenant_id كأمر غير قابل للتفاوض:
- اجعل
tenant_idمطلوبًا (NOT NULL) في الجداول المملوكة للمستأجر - أضف فهارس تبدأ بـ
tenant_id(مثلtenant_id, created_at) - اجعل قواعد التفرد تتضمن
tenant_id(مثل البريد الإلكتروني الفريد لكل مستأجر) - مرّر
tenant_idعبر كل واجهة برمجة الأعمال، ليس فقط نماذج الواجهة - نفّذ ذلك في الباكند، لا تعتمد فقط على فلاتر العميل
في PostgreSQL، سياسات مستوى الصف تمنح شبكة أمان قوية، خصوصًا عند توليد الاستعلامات ديناميكيًا.
عادةً ما تتبع بيانات المرجع أحد مسارين: جداول مشتركة (مثل countries) بدون tenant_id، أو كتالوجات نطاق-مستأجر (مثل الوسوم المخصصة) التي تتضمن tenant_id.
إذا كنت تبني باستخدام AppMaster، عادةً ما يمنع عادة بسيطة أغلب الحوادث: عيّن tenant_id من مستأجر المستخدم المصادق بعد المصادقة قبل أي إنشاء أو قراءة في منطق Business Process، واحتفظ بهذا النمط ثابتًا.
تأثير الصلاحيات: ماذا يتغير مع كل نهج
الصلاحيات هي المكان الذي ينجح أو يفشل فيه تعدد المستأجرين. تخطيط البيانات الذي تختاره يغير كيفية تخزين المستخدمين، كيفية تحديد نطاق الاستعلامات، وكيف تتجنب لحظات "الخطأ" في شاشات الإدارة.
مع قاعدة بيانات واحدة وtenant_id على كل صف، غالبًا ما تستخدم الفرق جدول Users مشتركًا وتربط كل مستخدم بمستأجر ودور أو أكثر. القاعدة الكبيرة تبقى: كل قراءة وكتابة يجب أن تتضمن نطاق المستأجر، حتى للجداول "الصغيرة" مثل الإعدادات، الوسوم، أو السجلات.
مع المخططات المنفصلة، غالبًا تحتفظ بطبقة هوية مشتركة (تسجيل الدخول، كلمة المرور، MFA) في مكان واحد، بينما تعيش بيانات المستأجر في مخطط لكل مستأجر. تصبح الصلاحيات جزءًا من مشكلة التوجيه: يجب أن يوجّه التطبيق الاستعلامات إلى المخطط الصحيح قبل تشغيل منطق الأعمال.
مع قواعد البيانات المنفصلة، العزل أقوى، لكن منطق الصلاحيات ينتقل إلى البنية التحتية: اختيار اتصال قاعدة البيانات الصحيح، إدارة بيانات الاعتماد، والتعامل مع حسابات الموظفين "العالمية".
عبر كل النهج الثلاثة، هناك أنماط تقلل المخاطر:
- ضع
tenant_idفي الجلسة أو مطالبات المصادقة واعتبره مطلوبًا. - مركّز فحوصات المستأجر في مكان واحد (middleware أو Business Process مشترك)، لا تنثرها عبر النقاط الطرفية.
- في أدوات الإدارة، أظهر سياق المستأجر بوضوح واطلب تبديل مستأجر صريح.
- للوصول الفني، استخدم الانتحال مع سجل تدقيق.
في AppMaster، يعني هذا عادةً تخزين سياق المستأجر مباشرة بعد المصادقة وإعادة استخدامه في نقاط النهاية وBusiness Processes حتى تبقى كل الاستعلامات محددة النطاق. يجب ألا يرى وكيل الدعم الطلبات إلا بعد أن يحدد التطبيق سياق المستأجر، وليس لأن الواجهة صادفًا قامت بالفلترة بشكل صحيح.
التقارير والأداء مع نموذج tenant_id
مع نهج قاعدة بيانات واحدة وtenant_id، عادةً ما تكون التقارير بسيطة. لوحات التحكم العالمية (MRR، التسجيلات، الاستخدام) يمكنها تنفيذ استعلام واحد عبر الجميع، وتقارير مستوى المستأجر هي نفس الاستعلام مع فلتر.
المقايضة هي الأداء مع الوقت. مع نمو الجداول، يمكن لمستأجر مزدحم أن يصبح جارًا مزعجًا بصياغة صفوف أكثر، ورفع عدد الكتابات، وجعل الاستعلامات الشائعة أبطأ إذا اضطرت القاعدة لمسح الكثير.
الفهرسة تحافظ على صحة هذا النموذج. ينبغي أن تتمكن معظم قراءات نطاق المستأجر من استخدام فهرس يبدأ بـ tenant_id، حتى تتمكن قاعدة البيانات من القفز مباشرة إلى شريحة ذلك المستأجر.
خط أساس جيد:
- أضف فهارس مركبة حيث يكون
tenant_idالعمود الأول (مثلtenant_id + created_at,tenant_id + status,tenant_id + user_id) - احتفظ بالفهارس العالمية الحقيقية فقط عند الحاجة لاستعلامات عبر المستأجرين
- راقب الانضمامات والفلاتر التي "تنسى"
tenant_id، لأنها تسبب مسوحات بطيئة
الاحتفاظ والحذف يحتاجان خطة أيضًا لأن سجل تاريخ مستأجر واحد يمكن أن ينفخ الجداول للجميع. إذا كان لدى المستأجرين سياسات احتفاظ مختلفة، فكر في حذف ناعم مع أرشفة مجدولة لكل مستأجر، أو نقل الصفوف القديمة إلى جدول أرشيف مفهرس بـ tenant_id.
النهج 2: مخططات منفصلة لكل مستأجر
مع المخططات المنفصلة، لا تزال تستخدم قاعدة PostgreSQL واحدة، لكن كل مستأجر يحصل على مخطط خاص به (مثال: tenant_42). الجداول داخل ذلك المخطط تخص فقط ذلك المستأجر. يبدو الأمر كما لو أن كل عميل لديه "قاعدة بيانات مصغرة" دون العبء الكبير لتشغيل قواعد بيانات عديدة.
إعداد شائع يحتفظ بالخدمات العالمية في مخطط مشترك وبيانات المستأجر في مخططات المستأجرين. الانقسام عادةً يدور حول ما يجب مشاركته بين كل العملاء مقابل ما لا يجب اختلاطه أبدًا.
تقسيم نموذجي:
- مخطط مشترك: جدول tenants، الخطط، سجلات الفوترة، أعلام الميزات، إعدادات التدقيق
- مخطط المستأجر: جداول الأعمال مثل الطلبات، التذاكر، المخزون، المشاريع، الحقول المخصصة
- كلا الجانبين (حسب المنتج): المستخدمون والأدوار، خصوصًا إن كان المستخدمون يمكنهم الوصول إلى مستأجرين متعددين
هذا النموذج يقلل خطر الانضمامات عبر المستأجرين لأن الجداول تعيش في مساحات أسماء مختلفة. كما يسهل نسخ أو استعادة مستأجر واحد باستهداف مخطط واحد.
ما يفاجئ الفرق هو الترحيلات. عندما تضيف جدولًا جديدًا أو عمودًا، يجب تطبيق التغيير على كل مخطط مستأجر. مع 10 مستأجرين يكون الأمر قابلًا للإدارة. مع 1000، تحتاج عملية: تتبع إصدارات المخططات، تشغيل الترحيلات على دفعات، والفشل بأمان حتى لا يعرقل مستأجر واحد الباقي.
الخدمات المشتركة مثل المصادقة والفوترة عادةً تعيش خارج مخططات المستأجر. نمط عملي هو مصادقة مشتركة (جدول مستخدم واحد مع جدول عضوية المستأجر) وفوترة مشتركة (معرفات عملاء Stripe، فواتير)، بينما تخزن مخططات المستأجر بيانات الأعمال الخاصة بالمستأجر.
إن كنت تستخدم AppMaster، خطّط مبكرًا كيف تُطابق نماذج Data Designer إلى المخططات المشتركة مقابل مخططات المستأجر، وحافظ على استقرار الخدمات العالمية حتى تتطور مخططات المستأجر دون كسر تسجيل الدخول أو المدفوعات.
التقارير والأداء مع المخططات المنفصلة
المخططات المنفصلة تمنح عزلًا افتراضيًا أقوى من نموذج tenant_id لأن الجداول مادية ومميزة ويمكن ضبط الصلاحيات على مستوى المخطط.
التقارير جيدة عندما تكون معظم التقارير على مستوى المستأجر. تبقى الاستعلامات بسيطة لأنك تقرأ من جداول مستأجر واحد دون الترشيح المستمر. يدعم هذا النموذج أيضًا "مستأجرين خاصين" يحتاجون جداول إضافية أو أعمدة مخصصة دون إجبار الباقين على حملها.
التقارير المجمعة عبر كل المستأجرين هي النقطة التي تصبح فيها المخططات مرهقة. إما تحتاج طبقة تقارير تستطيع الاستعلام من مخططات متعددة، أو تحتفظ بجدوال ملخصة مشتركة في مخطط مركزي.
أنماط شائعة:
- لوحات لكل مستأجر تستعلم جداول ذلك المستأجر فقط
- مخطط تحليلات مركزي مع ملخصات ليلية من كل مستأجر
- وظائف تصدير تنقل بيانات المستأجر إلى صيغة مناسبة للمخزن التحليلي
عادةً ما يكون الأداء جيدًا لأعباء مستوى المستأجر. الفهارس أصغر لكل مستأجر، والكتابات الثقيلة في مخطط واحد أقل احتمالًا أن تؤثر في الآخرين. المقايضة هي العبء التشغيلي: إنشاء مستأجر جديد يعني إنشاء مخطط، تشغيل الترحيلات، والحفاظ على تزامن المخططات عند تغير النموذج.
المخططات مناسبة عندما تريد عزلًا أشد دون تكلفة قواعد بيانات متعددة، أو عندما تتوقع تخصيصًا لكل مستأجر.
النهج 3: قاعدة بيانات منفصلة لكل مستأجر
مع قاعدة بيانات منفصلة لكل مستأجر، يحصل كل عميل على قاعدة بياناته الخاصة (أو قاعدة على نفس الخادم). هذا الخيار الأكثر عزلاً: إن تلفت بيانات مستأجر، أو خَرَج تحميل، فمن غير المرجح أن ينتشر إلى الآخرين.
يناسب هذا السيناريو البيئات المنظمة (صحة، مالية، حكومية) أو عملاء المؤسسات الذين يتوقعون فصلًا صارمًا، قواعد احتفاظ مخصصة، أو أداء مخصص.
تصبح عملية الانضمام سير عمل تقديمي. عند تسجيل مستأجر جديد، يحتاج نظامك إلى إنشاء أو استنساخ قاعدة بيانات، تطبيق المخطط الأساسي (جداول، فهارس، قيود)، إنشاء بيانات اعتماد وتخزينها بأمان، وتوجيه طلبات API إلى قاعدة البيانات الصحيحة.
إن كنت تبني باستخدام AppMaster، خيار التصميم الأساسي هو أين تحتفظ بدليل المستأجر (خريطة مركزية من مستأجر إلى اتصال قاعدة البيانات) وكيف تضمن أن كل طلب يستخدم الاتصال الصحيح.
الترقيات والترحيلات هي المقايضة الرئيسية. تغيير مخطط لم يعد "تشغيل مرة واحدة"، بل "تشغيل لكل مستأجر". هذا يزيد العمل التشغيلي والمخاطر، لذا غالبًا ما تعتمد الفرق نظام إصدار للمخططات وتشغّل الترحيلات كمهام مسيطَرة تتعقّب التقدم لكل مستأجر.
الميزة هي التحكم. يمكنك ترحيل المستأجرين الكبار أولًا، مراقبة الأداء، ثم نشر التغييرات تدريجيًا.
التقارير والأداء مع قواعد البيانات المنفصلة
قواعد البيانات المنفصلة الأسهل للفهم من حيث الحوادث العرضية: قراءة عبر المستأجرين نادرة الاحتمال، وأخطاء الصلاحية تؤثر عادة على مستأجر واحد فقط.
الأداء أيضًا نقطة قوة. الاستعلامات الثقيلة، الاستيرادات الكبيرة، أو تقرير جارٍ في مستأجر أ لن تبطئ مستأجر ب. هذا حماية قوية من الجيران المزعجين، وتتيح ضبط الموارد لكل مستأجر.
المقايضة تظهر في التقارير. التحليلات العالمية تصبح الأصعب لأن البيانات مجزأة فعليًا. أنماط عملية تشمل نسخ الأحداث أو الجداول الرئيسية إلى قاعدة تقارير مركزية، إرسال الأحداث إلى مخزن بيانات، تشغيل تقارير مستأجرية وتجميع النتائج (عندما يكون عدد المستأجرين صغيرًا)، وفصل مقاييس المنتج عن بيانات العملاء.
التكلفة التشغيلية عنصر آخر كبير. قواعد بيانات أكثر تعني نسخًا احتياطية أكثر، ترقّيًا وإدارة ومراقبة أكثر. قد تواجه أيضًا حدود اتصالات أسرع لأن كل مستأجر قد يحتاج مجموعة اتصالات خاصة به.
أخطاء شائعة تسبب تسرب بيانات أو ألم لاحقًا
معظم مشاكل تعدد المستأجرين ليست فشل تصميم كبير. إنها سهوات صغيرة تكبر إلى ثغرات أمنية، تقارير فوضوية، وتنظيف مكلف. تعمل تعددية المستأجرين عندما يُعامل فصل المستأجر كعادة، لا كميزة تضيفها لاحقًا.
تسريب شائع هو نسيان حقل المستأجر على جدول واحد، خصوصًا جداول الربط مثل user_roles, invoice_items, أو الوسوم. كل شيء يبدو صحيحًا حتى ينضم تقرير أو بحث عبر ذلك الجدول ويسحب صفوف من مستأجر آخر.
مشكلة متكررة هي لوحات الإدارة التي تتجاوز ترشيح المستأجر. غالبًا يبدأ الأمر كأداة "للدعم فقط" ثم يُعاد استخدامها. أدوات بلا كود لا تغير الخطر هنا: كل استعلام، عملية تجارية، ونقطة نهاية تقرأ بيانات المستأجر يجب أن تستخدم نفس نطاق المستأجر.
المعرفات أيضًا قد تخدعك. إن شاركت معرفات قابلة للقراءة بين المستأجرين (مثل order_number = 1001) وافترضت أنها فريدة عالميًا، ستخلط أدوات الدعم والتكاملات السجلات. احتفظ بمعرفات متميزة للمستأجر في عمليات البحث، وضمّن سياق المستأجر في عمليات البحث.
أخيرًا، تقلل الفرق من شأن الترحيلات والنسخ الاحتياطية مع التوسع. ما سهل مع 10 مستأجرين يصبح بطيئًا وخطيرًا مع 1000.
فحوصات سريعة تمنع معظم الألم:
- اكتب ملكية المستأجر صريحة على كل جدول، بما في ذلك جداول الربط.
- استخدم نمط تحديد نطاق واحد وأعد استخدامه في كل مكان.
- تأكد أن التقارير والتصديرات لا تُشغّل بدون نطاق مستأجر ما لم تكن حقًا عامة.
- تجنّب معرفات غامضة للمستأجر في APIs وأدوات الدعم.
- مرّن خطوات الاستعادة والترحيل مبكرًا، لا بعد النمو.
مثال: وكيل دعم يبحث عن "invoice 1001" ويجلب المستأجر الخطأ لأن عملية البحث تخطت نطاق المستأجر. خطأ صغير بتأثير كبير.
قائمة تحقق سريعة قبل الالتزام
قبل أن تقفل على نموذج البيانات متعدد المستأجرين، نفّذ بعض الاختبارات. الهدف هو اكتشاف تسريبات البيانات مبكرًا والتأكد أن قرارك يعمل عندما تكبر الجداول.
فحوصات سريعة يمكنك إجراؤها خلال يوم
- دليل عزل البيانات: أنشئ مستأجرين (A وB)، أضف سجلات متشابهة، ثم تحقق من أن كل قراءة وتحديث مقيدة بالمستأجر النشط. لا تعتمد على فلاتر الواجهة فقط.
- اختبار كسر الصلاحيات: سجّل دخول مستخدم من Tenant A وحاول فتح أو تعديل أو حذف سجل Tenant B بتغيير معرف السجل فقط. إن نجح أي شيء، اعتبره عائقًا للإصدار.
- سلامة مسار الكتابة: تأكد أن السجلات الجديدة تحصل دائمًا على قيمة المستأجر الصحيحة (أو تقع في المخطط/القاعدة الصحيحة)، حتى عند الإنشاء عبر وظائف خلفية، استيرادات، أو أتمتات.
- تجربة التقارير: تأكد أنك تستطيع تشغيل تقرير خاص بمستأجر واحد وتقرير "كل المستأجرين" (للموظفين الداخليين)، مع قواعد واضحة من يمكنه رؤية العرض العالمي.
- فحص الأداء: أضف استراتيجية فهرسة الآن (خاصة
(tenant_id, created_at)ومرشحات شائعة أخرى)، وقِس على الأقل استعلامًا بطيئًا عن قصد حتى تعرف شكل "السيء".
لجعل اختبار التقارير ملموسًا، اختر سؤالين تحتاجهما (واحد على مستوى مستأجر، وآخر عالمي) وشغّلهما على بيانات عيّنة.
-- Tenant-only: last 30 days, one tenant
SELECT count(*)
FROM tickets
WHERE tenant_id = :tenant_id
AND created_at >= now() - interval '30 days';
-- Global (admin): compare tenants
SELECT tenant_id, count(*)
FROM tickets
WHERE created_at >= now() - interval '30 days'
GROUP BY tenant_id;
إن كنت تُجرب في AppMaster، بنِ هذه الفحوصات في Business Process flows (قراءة، كتابة، حذف)، وملأ مستأجرين اثنين في Data Designer. عندما تنجح هذه الاختبارات بحجم بيانات واقعي، يمكنك الالتزام بثقة.
سيناريو مثالي: من أول العملاء إلى التوسع
شركة من 20 شخصًا تطلق بوابة عملاء: فواتير، تذاكر، ولوحة بسيطة. يتوقعون 10 مستأجرين في الشهر الأول، وخطة للوصول إلى 1000 خلال السنة التالية.
في البداية، النموذج الأبسط عادةً قاعدة بيانات واحدة مع tenant_id في كل جدول يخزن بيانات العميل. سريع للبناء، سهل للتقارير، ويجنب تكرار الإعداد.
مع 10 مستأجرين، الخطر الأكبر ليس الأداء بل الصلاحيات. فلتر مفقود (مثل استعلام "قائمة الفواتير" الذي نسي tenant_id) يمكن أن يسرّب بيانات. يجب على الفريق فرض فحوصات المستأجر في مكان واحد وتفTreat اشتراط نطاق المستأجر كقيد لا تفاوض عليه.
عند الانتقال من 10 إلى 1000، تتغير الاحتياجات. تصبح التقارير أثقل، ويطلب الدعم "تصدير كل شيء لهذا المستأجر"، ويبدأ بعض المستأجرين الكبار بالهيمنة على الحركة وإبطاء الجداول المشتركة.
مسار ترقية عملي غالبًا ما يبدو هكذا:
- احتفظ بنفس منطق التطبيق وقواعد الصلاحيات، لكن انقل المستأجرين ذوي الحجم الكبير إلى مخططات منفصلة.
- للمستأجرين الأكبر أو عملاء الامتثال الصارمين، حوّلهم إلى قواعد بيانات منفصلة.
- حافظ على طبقة تقارير مشتركة تقرأ من كل المستأجرين، وجدول تقارير كثيفة خارج ساعات الذروة.
اختر أبسط نموذج يحافظ على فصل آمن اليوم، ثم خطط لمسار هجرة لمشكلة "بضع مستأجرين ضخام" بدلًا من التحسين لها من اليوم الأول.
الخطوات التالية: اختر نموذجًا وجربه في باكند بلا كود
اختر بناءً على ما تحتاج حمايته أولًا: عزل البيانات، بساطة التشغيل، أم قابلية التوسع على مستوى المستأجر. الثقة تأتي من بناء نموذج أولي ومحاولة كسره بحالات صلاحيات وتقارير حقيقية.
دليل بداية بسيط:
- إن كان معظم المستأجرين صغيرًا وتحتاج تقارير عبر المستأجرين بسهولة، ابدأ بقاعدة بيانات واحدة و
tenant_idفي كل صف. - إن كنت تحتاج عزلًا أقوى لكن تفضل إدارة قاعدة بيانات واحدة، فكّر في مخططات منفصلة لكل مستأجر.
- إن طالب المستأجرون بعزل صارم (امتثال، نسخ احتياطي مخصص، خطر الجيران المزعجين)، فكّر في قاعدة بيانات منفصلة لكل مستأجر.
قبل البناء، اكتب حدود المستأجر بلغة واضحة. حدّد الأدوار (owner, admin, agent, viewer)، ما يقدر كل دور فعله، وما معنى البيانات "العالمية" (خطط، قوالب، سجلات التدقيق). قرر كيف تعمل التقارير: خاصة بالمستأجر فقط أم "جميع المستأجرين" للموظفين الداخليين.
إن كنت تستخدم AppMaster، يمكنك نمذجة هذه الأنماط بسرعة: صمّم الجداول في Data Designer (بما في ذلك tenant_id, قيود التفرد، والفهارس التي تعتمد عليها استعلاماتك)، ثم فرض القواعد في Business Process Editor حتى تبقى كل قراءة وكتابة محددة بنطاق المستأجر. إذا أردت نقطة مرجعية للمنصة، AppMaster متوفر على appmaster.io.
اختبار عملي نهائي: أنشئ مستأجرين اثنين (A وB)، أضف مستخدمين وطلبات متشابهة، وشغّل نفس التدفقات لكل منهما. جرّب تصدير تقرير للمستأجر A، ثم مرّر عمدًا معرفات المستأجر B إلى نفس النقاط الطرفية. نموذجك الأولي "آمن بما يكفي" فقط عندما تفشل هذه المحاولات دائمًا وتقاريرك الأساسية لا تزال سريعة بحجوم بيانات واقعية.
الأسئلة الشائعة
افترض قاعدة بيانات واحدة مع عمود tenant_id في كل جدول مملوك للمستأجر إذا أردت أبسط عملية وتحليلات عبر المستأجرين بشكل متكرر. انتقل إلى مخططات منفصلة عندما تحتاج عزلًا أقوى أو تخصيصًا لكل مستأجر دون إدارة قواعد بيانات عديدة. اختر قواعد بيانات منفصلة عندما تفرض المتطلبات التنظيمية أو عملاء المؤسسات حاجة لعزل صارم وتحكم بالآداء لكل مستأجر.
عامل تحديد نطاق المستأجر كأمر إلزامي في الباكند، وليس كفلتر في الواجهة فقط. اجعل tenant_id مطلوبًا في الجداول المملوكة للمستأجر، واستخرجه دائمًا من سياق المستخدم المصادق عليه بدل الوثوق بمدخلات العميل. أضف شبكة أمان مثل سياسات مستوى الصف في PostgreSQL إن كانت مناسبة، وابنِ اختبارات تحاول الوصول إلى سجلات مستأجر آخر بتغيير المعرف فقط.
ضع tenant_id كبداية للفهارس التي تطابق الفلاتر الشائعة حتى تقفز قاعدة البيانات مباشرة إلى مقطع بيانات المستأجر. خط أساس شائع هو فهرسة (tenant_id, created_at) لعرضات زمنية، وإضافة (tenant_id, status) أو (tenant_id, user_id) لمرشحات اللوحات. واجعل قواعد التفرد مرتبطة بالمستأجر، مثل البريد الإلكتروني الفريد لكل مستأجر.
المخططات المنفصلة تقلل من حالات الانضمام العرضية بين المستأجرين لأن الجداول تعيش في مساحات أسماء مختلفة، ويمكن ضبط الصلاحيات على مستوى المخطط. الجانب السلبي الرئيسي هو الترقيات: كل مخطط يحتاج نفس التغيير، ويصبح ذلك مشكلة عملية مع تزايد عدد المستأجرين. هو حل وسط جيد عندما تريد عزلًا أقوى من tenant_id لكن دون إدارة قواعد بيانات متعددة.
قواعد البيانات المنفصلة تقلل نصف المسافة للانفجار: ارتفاع التحميل أو خطأ التكوين أو تلف البيانات من المرجح أن يبقى محدودًا بمستأجر واحد. التكلفة هي عبء تشغيلي أكبر لأن عمليات التزويد والنسخ الاحتياطي والمراقبة والترقيات تتكرر لكل مستأجر. تحتاج أيضا إلى دليل مستأجر موثوق وإعادة توجيه للطلبات بحيث يستخدم كل استدعاء API الاتصال الصحيح.
التقارير عبر المستأجرين أسهل في قاعدة بيانات واحدة مع tenant_id لأن لوحات التحكم العامة هي استعلامات بدون فلاتر المستأجر. مع المخططات أو قواعد البيانات المنفصلة، تعمل التحليلات العالمية عادةً بنسخ أحداث أو ملخصات رئيسية إلى متجر تقارير مشترك مجدولًا. اجعل قاعدة بسيطة: مقاييس المنتج الشاملة تذهب إلى طبقة التقارير، بينما تبقى بيانات المستأجرين معزولة.
اجعل سياق المستأجر صريحًا في أدوات الدعم واشتَرِط تبديل مستأجر واضح قبل عرض السجلات. إن استخدمت الانتحال (impersonation)، سجّل من وصل إلى ماذا ومتى، واجعل الوصول محدودًا زمنياً. تجنّب رحلات العمل التي تقبل معرف سجل بدون سياق المستأجر، لأن ذلك هو سبب أخطاء مثل "invoice 1001" التي تتحول إلى تسريبات حقيقية.
إذا احتاج المستأجرون لحقول أو سير عمل مختلفة، فتقليل التأثير المتبادل أسهل بالمخططات أو قواعد البيانات المنفصلة. إن كان معظمهم متشابهين، احتفظ بنموذج واحد مع tenant_id وتعامل مع الاختلافات عبر إعدادات قابلة للتهيئة مثل أعلام الخصائص أو الحقول الاختيارية. المفتاح هو تجنّب الجداول "شبه العالمية" التي تخلط بين معانٍ مشتركة وخاصة دون ملكية واضحة.
قرّر حدود المستأجر مبكرًا: أين يُخزن سياق المستأجر بعد المصادقة وتأكد أن كل قراءة/كتابة تستخدمه. في AppMaster، يعني هذا عادةً تعيين tenant_id من المستخدم المصادق في منطق Business Process قبل إنشاء أو استعلام السجلات المملوكة للمستأجر، بحيث لا تنسى النقاط الطرفية ذلك. اعتبر هذا نمطًا قابلاً لإعادة الاستخدام تطبقه في كل مكان.
أنشئ مستأجرين اثنين ببيانات متشابهة وحاول كسر العزل بتغيير معرفات السجلات أثناء عمليات القراءة والتحديث والحذف. تحقّق أن الوظائف الخلفية، وعمليات الاستيراد، والتصدير تكتب دائمًا في نطاق المستأجر الصحيح لأن تلك المسارات سهلة التغاضي عنها. كذلك شغّل تقريرًا على مستوى مستأجر وتقريرًا إداريًا عالميًا مقابل حجم بيانات نموذجي لتتأكد من أن الأداء وقواعد الوصول صامدان.


