دليل النشر

استضافة MySQL على خادم VPS: دليل شامل

انشر على VPS Cloud ←

دليل عملي

استضافة MySQL على خادم VPS: دليل شامل

قواعد البيانات9 دقائق للقراءةعدد الخطوات: 6

يُشغّل ‎MySQL‎ جزءًا هائلًا من الويب: ‎WordPress‎ و‎Magento‎ و‎Laravel‎ وآلاف تطبيقات ‎PHP‎. استضافته ذاتيًا على خادم ‎VPS‎ تمنحك أداءً مخصصًا، وتحكمًا كاملًا في إعدادات ‎InnoDB‎، وتكاليف مضبوطة، بعيدًا عن قيود الاستضافة المشتركة.

المحتويات· لماذا تستضيف MySQL ذاتيًا على خادم VPS1/9
  1. 01لماذا تستضيف MySQL ذاتيًا على خادم VPS
  2. 02الفوائد الملموسة لـ MySQL مُستضاف ذاتيًا
  3. 03المتطلبات الأساسية قبل البدء
  4. 04نشر MySQL 8.4 باستخدام Docker في بيئة الإنتاج
  5. 05التأمين: الإجراءات الأساسية
  6. 06تحسين أداء InnoDB
  7. 07الوصول البعيد الآمن: نفق SSH
  8. 08النسخ الاحتياطية التلقائية: استراتيجية شاملة
  9. 09استكشاف الأخطاء: 5 أخطاء شائعة

لماذا تستضيف MySQL ذاتيًا على خادم VPS

على الاستضافة المشتركة، تتقاسم قاعدة بيانات ‎MySQL‎ الخاصة بك ذاكرة ‎RAM‎ وعمليات الإدخال/الإخراج مع مئات المواقع الأخرى، ولا يمكنك تعديل innodb_buffer_pool_size ولا أوضاع ‎SQL‎ ولا إصدار المحرك. على خادم ‎VPS‎، تحصل على موارد مخصصة، وتختار بين ‎MySQL 8.4 LTS‎ و‎MariaDB‎، وتصل إلى ملف my.cnf لتحسين كل معامل. إنه الخيار الصحيح لمتجر تجارة إلكترونية، أو نظام إدارة محتوى عالي الحركة، أو واجهة برمجية (‎API‎) تحتاج إلى معاملات سريعة و‎buffer pool‎ سخي. كما تدير المستخدمين الخاصين بك، وصلاحيات المنح (‎grants‎) على مستوى الجداول، واستراتيجية النسخ المتماثل بين الخادم الرئيسي والتابع.

الفوائد الملموسة لـ MySQL مُستضاف ذاتيًا

  • موارد مخصصة: كامل ‎buffer pool‎ الخاص بـ ‎InnoDB‎ لبياناتك، دون جيران مزعجين.
  • وصول كامل إلى my.cnf: innodb_buffer_pool_size وmax_connections وأوضاع ‎SQL‎ الصارمة.
  • اختيار المحرك: ‎MySQL 8.4 LTS‎ للاستقرار طويل الأمد، أو ‎MariaDB‎ لمحركاتها الإضافية.
  • نسخ متماثل بين الخادم الرئيسي والتابع قابل للتهيئة لتوزيع عمليات القراءة أو التعافي من الأعطال.
  • نسخ احتياطية منطقية (mysqldump) أو فيزيائية (xtrabackup) حسب حجم بياناتك.
  • لا حصص تعسفية على حجم قواعد البيانات أو عدد الاتصالات المتزامنة.

المتطلبات الأساسية قبل البدء

الإصدار الموصى به: ‎MySQL 8.4 LTS‎ (الإصدار الحالي: ‎8.4.11‎)، الفرع الرسمي للدعم طويل الأمد، مدعوم حتى عام 2032. تجنّب ‎MySQL 8.0‎ في التثبيتات الجديدة: ينتهي دعمه النشط في 2025.

ذاكرة RAM: 1 ‎GB‎ حدًّا أدنى لبيئة الاختبار أو مدونة خفيفة. خطّط لـ 2 ‎GB‎ لموقع ‎WordPress‎ أو تطبيق صغير في الإنتاج، و4 إلى 8 ‎GB‎ لـ ‎Magento‎ أو ‎PrestaShop‎ أو واجهة برمجية عالية الحركة. القاعدة الأساسية: خصّص 60 إلى 70% من ‎RAM‎ المتاحة لـ innodb_buffer_pool_size.

المعالج: 2 ‎vCPU‎ تكفي لمعظم الحالات. ارتقِ إلى 4 ‎vCPU‎ عند كثرة الاستعلامات أو تفعيل النسخ المتماثل.

التخزين: 30 ‎GB‎ من ‎SSD NVMe‎ كنقطة انطلاق؛ احتفظ بمساحة إضافية لملفات ‎binlogs‎ إن فعّلت النسخ المتماثل أو الاستعادة إلى نقطة زمنية محددة.

المنافذ: يستمع ‎MySQL‎ افتراضيًا على المنفذ 3306. يجب ألّا يكون هذا المنفذ مفتوحًا على الواجهة العامة. يجب أن يُشير المعامل bind-address في my.cnf إلى 127.0.0.1 أو عنوان الشبكة الخاصة، لا إلى 0.0.0.0.

النظام: ‎Ubuntu 22.04‎ أو ‎24.04 LTS‎، و‎Docker‎ و‎Docker Compose v2‎، ووحدة تخزين دائمة مخصصة.

نشر MySQL 8.4 باستخدام Docker في بيئة الإنتاج

  1. تأمين خادم VPS

    حدّث النظام (apt update && apt upgrade -y)، وثبّت ‎Docker‎، وعطّل الدخول عبر ‎SSH‎ بكلمة المرور لصالح المفاتيح (PasswordAuthentication no في sshd_config)، وأغلق المنفذ 3306 نحو الخارج:

    ufw deny 3306
    ufw allow OpenSSH
    ufw enable

    يجب ألّا يستمع ‎MySQL‎ إلا على الشبكة الداخلية لحاوية ‎Docker‎.

  2. تعريف ملف docker-compose.yml

    أعلن عن خدمة mysql:8.4، وركّب وحدة تخزين على /var/lib/mysql، ومرّر متغيرات البيئة عبر ملف .env:

    # .env
    MYSQL_ROOT_PASSWORD=كلمة_مرور_root_قوية
    MYSQL_DATABASE=قاعدة_بياناتي
    MYSQL_USER=app_user
    MYSQL_PASSWORD=كلمة_مرور_التطبيق
    # docker-compose.yml
    services:
      mysql:
        image: mysql:8.4
        restart: unless-stopped
        env_file: .env
        volumes:
          - mysql_data:/var/lib/mysql
          - ./conf.d:/etc/mysql/conf.d:ro
        ports:
          - "127.0.0.1:3306:3306"
    volumes:
      mysql_data:

    لاحظ الربط بـ 127.0.0.1 في ports: لن يكون المنفذ متاحًا إلا من الخادم نفسه.

  3. إنشاء قاعدة بيانات ومستخدم مخصص

    بعد docker compose up -d، اتصل بالحاوية:

    docker exec -it mysql mysql -u root -p

    أنشئ قاعدة البيانات ومستخدم التطبيق:

    CREATE DATABASE قاعدة_بياناتي CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
    CREATE USER 'app_user'@'%' IDENTIFIED BY 'كلمة_مرور_التطبيق';
    GRANT SELECT, INSERT, UPDATE, DELETE ON قاعدة_بياناتي.* TO 'app_user'@'%';
    FLUSH PRIVILEGES;

    حصّر الصلاحيات في الحد الأدنى الضروري: لا تستخدم GRANT ALL PRIVILEGES أبدًا لحساب التطبيق.

  4. تعزيز أمان التثبيت

    نفّذ ما يعادل mysql_secure_installation يدويًا:

    -- حذف المستخدمين المجهولين
    DELETE FROM mysql.user WHERE User='';
    -- منع تسجيل دخول root عن بُعد
    DELETE FROM mysql.user WHERE User='root' AND Host NOT IN ('localhost', '127.0.0.1', '::1');
    -- حذف قاعدة البيانات التجريبية
    DROP DATABASE IF EXISTS test;
    FLUSH PRIVILEGES;

    لا تستخدم حساب root أبدًا من تطبيقك. تحقق من وجود bind-address = 127.0.0.1 في ملف conf.d/custom.cnf.

  5. الكشف عبر TLS عند الحاجة

    إذا كان على تطبيق خارجي الاتصال عن بُعد، لا تعرّض المنفذ 3306 مباشرة على الإنترنت. استخدم نفق SSH:

    ssh -L 3306:127.0.0.1:3306 [email protected] -N

    ثم اتصل بعميل ‎MySQL‎ على 127.0.0.1:3306 — يمر التراسل مشفرًا عبر ‎SSH‎. للاتصال الدائم بين خوادم ‎VPS‎، هيّئ ‎MySQL‎ للاستماع على واجهة الشبكة الخاصة فقط واسمح فقط لعنوان ‎IP‎ الخادم التطبيقي في ‎UFW‎.

  6. جدولة النسخ الاحتياطية

    جدوِل mysqldump --single-transaction يوميًا عبر ‎cron‎ للحصول على نسخ متسقة دون قفل:

    # /etc/cron.d/mysql-backup
    0 2 * * * root docker exec mysql mysqldump -u root -p"${MYSQL_ROOT_PASSWORD}" --single-transaction --all-databases | gzip > /backups/mysql-$(date +\%Y\%m\%d).sql.gz

    احتفظ بما لا يقل عن 7 أيام من الاحتفاظ، وأرشف النسخ خارج خادم ‎VPS‎. اختبر الاستعادة مرة شهريًا: نسخة احتياطية غير مختبَرة ليست نسخة احتياطية. للقواعد الكبيرة، انتقل إلى ‎Percona XtraBackup‎.

التأمين: الإجراءات الأساسية

mysql_secure_installation في حاوية. لا تُنفّذ الصورة الرسمية لـ ‎Docker‎ هذا الأمر تلقائيًا: نفّذه يدويًا بعد أول تشغيل (الخطوة 4 أعلاه).

حذف root البعيد. يجب أن يكون حساب root متاحًا من localhost فقط. حساب ‎root‎ متاح من % هو أول ثغرة يستغلها فحص المنافذ.

مستخدم مخصص لكل تطبيق. يحصل كل تطبيق متصل على حسابه الخاص في ‎MySQL‎ بصلاحيات مقيدة بقاعدة بياناته. تطبيق معطوب لن يتمكن من قراءة أو تعديل بيانات التطبيقات الأخرى.

UFW + bind-address. الحماية المزدوجة إلزامية: ufw deny 3306 على مستوى جدار الحماية النظامي، وbind-address = 127.0.0.1 في my.cnf من جانب ‎MySQL‎. لا يُغني أحدهما عن الآخر.

كلمات مرور قوية. استخدم caching_sha2_password (الإضافة الافتراضية في ‎MySQL 8.x‎) وكلمات مرور مُولَّدة (20 حرفًا على الأقل). خزّنها في أسرار مُدارة، لا في الشفرة المصدرية أبدًا.

تحسين أداء InnoDB

تُضاف هذه المعاملات في ملف conf.d/custom.cnf المركَّب بوضع القراءة فقط في الحاوية.

innodb_buffer_pool_size: المعامل الأهم. اضبطه على 60–70% من ‎RAM‎ خادم ‎VPS‎. على خادم بـ 4 ‎GB‎، ذلك يعني 2.5 إلى 2.8 ‎GB‎. صغير جدًا = قراءات قرص متكررة؛ كبير جدًا = مبادلة (‎swap‎).

innodb_flush_log_at_trx_commit: القيمة 2 تُقدّم توازنًا جيدًا بين الأداء والمتانة لمعظم التطبيقات. القيمة 1 (الافتراضية) أكثر أمانًا لكنها أبطأ؛ القيمة 0 هي الأسرع لكنها محفوفة بالمخاطر عند الأعطال.

max_connections: اضبطه وفق حملك الفعلي. القيمة الافتراضية (151) غالبًا منخفضة جدًا للتطبيقات عالية الحركة. كل اتصال يستهلك ~1 ‎MB‎ من ‎RAM‎.

slow_query_log: فعّله بـ slow_query_log = 1 وlong_query_time = 1 لالتقاط كل الاستعلامات التي تتجاوز ثانية واحدة. هو أداتك الأولى للتحسين.

مثال على custom.cnf لخادم ‎VPS‎ بـ 4 ‎GB‎:

[mysqld]
innodb_buffer_pool_size = 2G
innodb_flush_log_at_trx_commit = 2
max_connections = 200
slow_query_log = 1
long_query_time = 1
log_bin = /var/lib/mysql/binlog
binlog_format = ROW

الوصول البعيد الآمن: نفق SSH

تعريض المنفذ 3306 على الواجهة العامة لخادم ‎VPS‎ خطأ أمني جسيم: تحاول الماسحات التلقائية هجمات القوة الغاشمة على هذا المنفذ باستمرار. النهج الصحيح هو نفق ‎SSH‎.

اتصال لمرة واحدة من جهازك:

ssh -L 3306:127.0.0.1:3306 [email protected] -N

افتح بعد ذلك عميل ‎MySQL‎ على 127.0.0.1:3306 — يمر التراسل مشفرًا عبر ‎SSH‎.

اتصال دائم بين خوادم VPS: إذا كان تطبيقك يعمل على خادم ‎VPS‎ ثانٍ على نفس الشبكة الخاصة، هيّئ ‎MySQL‎ للاستماع على عنوان الشبكة الخاصة فقط (bind-address = 10.0.0.X)، واسمح فقط لعنوان ‎IP‎ الخادم التطبيقي في ‎UFW‎:

ufw allow from 10.0.0.5 to any port 3306

ما يجب تجنّبه: bind-address = 0.0.0.0 دون جدار حماية، المنفذ 3306 مفتوح علنًا، أو حسابات ‎MySQL‎ بـ Host='%' دون قيود ‎IP‎.

النسخ الاحتياطية التلقائية: استراتيجية شاملة

تعتمد استراتيجية النسخ الاحتياطي لـ ‎MySQL‎ على مستويين متكاملين.

المستوى الأول — نسخ منطقية يومية (mysqldump): متسقة بفضل --single-transaction (لا قفل قراءة على ‎InnoDB‎)، قابلة للنقل بين الإصدارات. مناسبة للقواعد حتى عشرات الـ ‎GB‎.

المستوى الثاني — binlogs للاستعادة إلى نقطة زمنية: فعّل log_bin منذ البداية. بدمجها مع نسخة كاملة أسبوعية، تتيح لك ‎binlogs‎ إعادة تشغيل كل معاملة حتى الثانية التي سبقت حادثة.

للقواعد الكبيرة — Percona XtraBackup: نسخ فيزيائية دون انقطاع الخدمة، استعادة سريعة (نسخ ملفات لا إعادة تنفيذ ‎SQL‎).

الاحتفاظ والأرشفة: لا تخزّن النسخ على خادم ‎VPS‎ فقط. خادم ‎VPS‎ معطوب يُضيّع نسخه الاحتياطية معه. صدّر إلى تخزين كائنات أو خادم ‎SFTP‎ بعيد، واحتفظ بـ 7 أيام على الأقل.

اختبار الاستعادة: نسخة غير مختبَرة ليست نسخة احتياطية. خطّط لاختبار شهري: استعِد على حاوية مؤقتة وتحقق من سلامة بياناتك.

# استعادة من نسخة مضغوطة
zcat /backups/mysql-20260917.sql.gz | docker exec -i mysql mysql -u root -p

استكشاف الأخطاء: 5 أخطاء شائعة

Access denied for user 'app'@'...'
الحساب موجود لكن Host لا يتطابق. يتحقق ‎MySQL‎ من عنوان ‎IP‎ المصدر بدقة. إذا اتصل التطبيق من حاوية ‎Docker‎، قد يكون عنوان ‎IP‎ المصدر 172.17.0.x لا localhost. تحقق بـ:

SELECT User, Host FROM mysql.user;

الحل: أنشئ الحساب بـ 'app_user'@'%' (أو عنوان ‎IP‎ الحاوية بالضبط) وأعد تشغيل FLUSH PRIVILEGES.

Too many connections
تم الوصول إلى max_connections. تحقق من عدد الاتصالات النشطة:

SHOW STATUS LIKE 'Threads_connected';

زِد max_connections في custom.cnf وتحقق من أن تطبيقك يستخدم مجمع اتصالات (‎connection pool‎).

Table '...' is marked as crashed
تلف ‎InnoDB‎، في الغالب بعد إيقاف مفاجئ. حاول الإصلاح:

mysqlcheck -u root -p --auto-repair --all-databases

إن تعذّر إصلاح الجدول، استعِد من آخر نسخة احتياطية متسقة.

Can't connect to MySQL server on '127.0.0.1' (111)
‎MySQL‎ لا يستمع على الواجهة المتوقعة. تحقق من bind-address في custom.cnf وأعد تشغيل الحاوية. تحقق أيضًا من أن الحاوية تعمل بـ docker compose ps.

ERROR 1819 (HY000): Your password does not satisfy the current policy
إضافة التحقق من كلمة المرور في ‎MySQL 8‎ ترفض كلمات المرور البسيطة. استخدم كلمة مرور بـ 8 أحرف على الأقل مع أحرف كبيرة وأرقام ورموز، أو اضبط validate_password.policy = LOW في custom.cnf لبيئات التطوير فقط.

فعّل ملفات ‎binlogs‎ (log_bin + binlog_format=ROW) منذ البداية: فهي مفتاح الاستعادة إلى نقطة زمنية محددة. وبدمجها مع mysqldump كامل أسبوعي، تتيح لك إعادة تشغيل جميع المعاملات حتى الثانية التي سبقت العطل. وإذا أنشأت تابعًا (‎replica‎) للنسخ المتماثل على خادم ‎VPS‎ ثانٍ، فإن ملفات ‎binlogs‎ نفسها تُغذّي النسخة التابعة في الوقت الفعلي لعمليات القراءة الموزّعة.

استضِف قاعدة بيانات MySQL على خادم VPS عالي الأداء

يمنحك خادم ServOrbit Cloud VPS مع قالب Docker جاهز للاستخدام أقراص SSD وموارد مضمونة لتشغيل MySQL دون أي تنازلات.

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

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

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