المحتوى عن 'database'.



مزيد من الخيارات

  • ابحث بالكلمات المفتاحية

    أضف وسومًا وافصل بينها بفواصل ","
  • ابحث باسم الكاتب

نوع المُحتوى


التصنيفات

  • التخطيط وسير العمل
  • التمويل
  • فريق العمل
  • دراسة حالات
  • نصائح وإرشادات
  • التعامل مع العملاء
  • التعهيد الخارجي
  • التجارة الإلكترونية
  • الإدارة والقيادة
  • مقالات ريادة أعمال عامة

التصنيفات

  • PHP
    • Laravel
    • ووردبريس
  • جافاسكريبت
    • Node.js
    • jQuery
    • AngularJS
    • Cordova
  • HTML
    • HTML5
  • CSS
  • SQL
  • سي شارب #C
    • منصة Xamarin
  • بايثون
    • Flask
    • Django
  • لغة روبي
    • Sass
    • إطار عمل Bootstrap
    • إطار العمل Ruby on Rails
  • لغة Go
  • لغة جافا
  • لغة Kotlin
  • برمجة أندرويد
  • لغة Swift
  • لغة R
  • لغة TypeScript
  • سير العمل
    • Git
  • صناعة الألعاب
    • Unity3D
  • مقالات برمجة عامة

التصنيفات

  • تجربة المستخدم
  • الرسوميات
    • إنكسكيب
    • أدوبي إليستريتور
    • كوريل درو
  • التصميم الجرافيكي
    • أدوبي فوتوشوب
    • أدوبي إن ديزاين
    • جيمب
  • التصميم ثلاثي الأبعاد
    • 3Ds Max
    • Blender
  • نصائح وإرشادات
  • مقالات تصميم عامة

التصنيفات

  • خواديم
    • الويب HTTP
    • قواعد البيانات
    • البريد الإلكتروني
    • DNS
    • Samba
  • الحوسبة السّحابية
    • Docker
  • إدارة الإعدادات والنّشر
    • Chef
    • Puppet
    • Ansible
  • لينكس
  • FreeBSD
  • حماية
    • الجدران النارية
    • VPN
    • SSH
  • مقالات DevOps عامة

التصنيفات

  • التسويق بالأداء
    • أدوات تحليل الزوار
  • تهيئة محركات البحث SEO
  • الشبكات الاجتماعية
  • التسويق بالبريد الالكتروني
  • التسويق الضمني
  • التسويق بالرسائل النصية القصيرة
  • استسراع النمو
  • المبيعات
  • تجارب ونصائح

التصنيفات

  • إدارة مالية
  • الإنتاجية
  • تجارب
  • مشاريع جانبية
  • التعامل مع العملاء
  • الحفاظ على الصحة
  • التسويق الذاتي
  • مقالات عمل حر عامة

التصنيفات

  • الإنتاجية وسير العمل
    • مايكروسوفت أوفيس
    • ليبر أوفيس
    • جوجل درايف
    • شيربوينت
    • Evernote
    • Trello
  • تطبيقات الويب
    • ووردبريس
    • ماجنتو
  • أندرويد
  • iOS
  • macOS
  • ويندوز

التصنيفات

  • شهادات سيسكو
    • CCNA
  • شهادات مايكروسوفت
  • شهادات Amazon Web Services
  • شهادات ريدهات
    • RHCSA
  • شهادات CompTIA
  • مقالات عامة

أسئلة وأجوبة

  • الأقسام
    • أسئلة ريادة الأعمال
    • أسئلة العمل الحر
    • أسئلة التسويق والمبيعات
    • أسئلة البرمجة
    • أسئلة التصميم
    • أسئلة DevOps
    • أسئلة البرامج والتطبيقات
    • أسئلة الشهادات المتخصصة

التصنيفات

  • ريادة الأعمال
  • العمل الحر
  • التسويق والمبيعات
  • البرمجة
  • التصميم
  • DevOps

تمّ العثور على 7 نتائج

  1. من الممكن أن تكون المعايرة مهمّة صعبة جدًا، وخاصّة عند العمل مع بيانات ضخمة، حيث أنّ أصغر تغيير من الممكن أن يتسبب بتغيرات غير متوقعه ( إيجابية أو سلبية) على الأداء ككل. تتم معظم عمليات معايرة SQl database في الشركات المتوسطة والصغيرة من قبل مدير قاعدة البيانات (Database Administrator (DBA، لكن صدقني، يوجد العديد من المطوّرين بحاجة للقيام بعمليات متعلقة بالإدارة، وأكثر من ذلك أنا شاهدت أنّهم يقومون فعليًّا بعمليات الإدارة في كثير من الشركات التي تتطلع للعمل مع المطوّرين، حين يتطلب الوضع ببساطة تقنيات مختلفة لحل المشاكل، والتي يمكن أن تؤدي إلى خلاف بين زملاء العمل. عند التعامل مع بيانات ضخمة، فإنّ التغيير الصغير قد يؤدي إلى تغيرات غير متوقعة على الأداء. وبناء على ذلك، فإنّ هيكلية الشبكة أيضًا لها تأثير، افترض أن فريق الإدارة DBA team مع قواعد البيانات التي يديرونها يتوضع في الطابق العاشر، بينما يتوضع المطوّرين في الطابق الخامس عشر، أو حتى في بناء مختلف تحت هيكلية منفصلة تمامًا، وبالتالي من الصعب العمل المشترك بينهم بمرونة تحت هذه الظروف، سأقوم بإتمام شيئين هامين في هذه المقالة: تزويد المطوّرين بتقنيات معايرة لقواعد بيانات خاصة بالمطوّرين. شرح كيف يمكن لمطوّري ومديري قواعد البيانات العمل معًا بكفاءة. تحسين قاعدة البيانات (في Codebase) الفهارس إذا كنت حديثًا في مجال قواعد البيانات أو حتى تسأل نفسك، “ماهي معايرة SQL”، فيجب أن تعلم أنّ الفهرسة هي طريقة فعّالة لمعايرة قاعدة البيانات database SQL الخاصة بك، والتي غالبًا ما يتم إهمالها خلال عملية التطوير، كمصطلح أولي: الفهرس index هو هيكلة للبيانات تسمح بتسريع عملية استخلاص هذه البيانات من جدول قاعدة البيانات، عن طريق تأمين عمليات بحث عشوائية سريعة، وطريقة فعّالة للوصول إلى السجلات المرتبة، هذا يعني أنّه حالما تقوم بإنشاء فهرس يمكنك القيام بعمليات الاستعلام والترتيب بشكل أسرع. تستخدم الفهارس أيضًا لتعريف المفتاح الرئيسي أو فهرس فريد يضمن أنّ أي عمود آخر لن يحتوي نفس القيمة. بالطبع إنّ موضوع الفهرسة متنوع وهام ولا يمكنني إعطاءه حقه في هذا الوصف الموجز. إذا كنت حديثًا على موضوع الفهرسة فأنا أفضل أن تستخدم هذا المخطط لهيكلة استعلاماتك. بشكل أولي، الهدف هو فهرسة أعمدة البحث والترتيب. لاحظ أنه إذا كانت تجري بشكل مستمر عمليات إدخال INSERT أو تعديل UPDATE أو حذف DELETE، فيجب عليك الحذر من القيام بعمليات الفهرسة، حيث يمكن أن يؤدي إلى هبوط في الأداء، إذ أنّه يتطلب تعديل جميع الفهارس بعد هذه العمليات. كذلك مديري قواعد البيانات يقومون بحذف الفهارس قبل القيام مثلًا بإدخال أكثر من مليون سجل دفعة واحدة، وذلك لتسريع عملية الإدخال، ثم يقومون بإعادة إنشاء الفهارس بعد انتهاء الإدخال، تذكر على أية حال أن حذف الفهارس يؤثر على كافة الاستعلامات على الجداول، لذلك هذه الطريقة محبذة فقط عند عملية إدخال واحدة ضخمة للبيانات. معايرة أداء SQL Server: خطط التنفيذ بالمناسبة، أداة خطة التنفيذ في SQL Server مفيدة لإنشاء الفهارس. مهمتها الأساسية تتمثل في الإظهار المرئي لطرق تحصيل البيانات المختارة من قبل منسق استعلام SQL Server. للحصول على خطة التنفيذ (في برنامج الإدارة SQL Server Management Studio)، قم فقط بالنقر على Include Actual Execution Plan" CTRL + M" قبل بدء تشغيل الاستعلام. بعدئذ ،سوف يظهر إطار ثالث اسمه “Execution Plan”، حيث يمكن أن تشاهد اكتشاف فهرس مفقود، ولإنشائه قم بالنقر بالزر اليميني على execution plan وقم باختيار Missing Index Details، بكل بساطة. معايرة استعلام SQL عن طريق تجنب حلقات الشفرة تخيّل سيناريو يقوم فيه 1000 استعلام بإضافة بيانات على قاعدة بياناتك بشكل تسلسلي، كالتالي: for (int i = 0; i < 1000; i++) { SqlCommand cmd = new SqlCommand("INSERT INTO TBL (A,B,C) VALUES..."); cmd.ExecuteNonQuery(); } يجب عليك تجنب مثل هذه الحلقات في شفرتك، وكمثال سنقوم بتحويل باستخدام العبارات الفريدة INSERT UPDATE مع أسطر وقيم عدّة. INSERT INTO TableName (A,B,C) VALUES (1,2,3),(4,5,6),(7,8,9) -- SQL SERVER 2008 INSERT INTO TableName (A,B,C) SELECT 1,2,3 UNION ALL SELECT 4,5,6 -- SQL SERVER 2005 UPDATE TableName SET A = CASE B WHEN 1 THEN 'NEW VALUE' WHEN 2 THEN 'NEW VALUE 2' WHEN 3 THEN 'NEW VALUE 3' END WHERE B in (1,2,3) تأكد من أن عبارة تتجنب تحديث القيم المخزنة إذا كانت تتطابق مع القيمة الموجودة. مثل هذه يمكن أن تحسّن أداء الاستعلام بشكل كبير عن طريق تعديل مئات السجلات بدل الآلاف وكمثال: UPDATE TableName SET A = @VALUE WHERE B = 'YOUR CONDITION' AND A <> @VALUE -- VALIDATION تجنّب الاستعلامات الفرعيّة المرتبطة Correlated Subqueries الاستعلامات المرتبطة هي الاستعلامات التي تستخدم قيم من الاستعلام الأب، هذه النوع من الاستعلامات ينحو إلى العمل سجل بعد سجل row-by-row، مرة لكل سجل معاد من الاستعلام الخارجي الأب، ولذلك فإنه ينقص أداء استعلام SQl. المطوّرين الحديثين غالبًا ما يبنون استعلاماتهم على هذه الشاكلة لأنها عادة الطريقة الأسهل. هنا تجد مثال عن الاستعلامات المرتبطة: SELECT c.Name, c.City, (SELECT CompanyName FROM Company WHERE ID = c.CompanyID) AS CompanyName FROM Customer c بشكل خاص، المشكلة تكون بأن الاستعلام الداخلي(...SELECT CompanyName) ينفذ لكل سجل مسترجع من الاستعلام الخارجي (...SELECT c.Name)، لكن لماذا العودة إلى مرّة ثم أخرى في كل مرة يعالج فيها سجل من الاستعلام الخارجي؟ التقنية الافضل لمعايرة الأداء تكون بمعاملة الاستعلام الفرعي كعملية ربط join SELECT c.Name, c.City, co.CompanyName FROM Customer c LEFT JOIN Company co ON c.CompanyID = co.CompanyID وبهذه الحالة نقوم بالمرور على جدول Company مرة واحدة ، نربطه بجدول Customer، وعندها يمكننا الحصول على القيم التي نريدها (co.CompanyName) بشكل أفضل. الاختيار باعتدال Select Sparingly واحدة من أهم نصائح المعايرة هو تجنب استخدام تعليمة SELECT * . وبدلًا من ذلك يجب تحديد الأعمدة التي تحتاجها فقط مره ثانية. هذا الأمر بسيط، لكن هذا الخطأ منتشر، افترض جدولًا بمئات الأعمدة وملايين السجلات فإذا كان تطبيقك يحتاج إلى عدد محدّد من الأعمدة فقط، فلا حاجة لاستجلاب جميع البيانات، لأن ذلك تضييع للمصادر كمثال: SELECT * FROM Employees مقابل SELECT FirstName, City, Country FROM Employees إذا كنت بالفعل تحتاج إلى كل الأعمدة ، قم بتسميتهم ضمن الاستعلام، هذه ليست قاعدة، لكنها طريقة للمعايرة و لتجنب الأخطاء المستقبلية. كمثال إذا كنت تستخدم التعليمة INSERT... ...SELECT وتم تغيير الجدول عن طريق إضافة عمود جديد، عندها ربما تقع في مشكلة إذا كان هذا العمود غير مطلوبًا في الجدول الهدف وكمثال: INSERT INTO Employees SELECT * FROM OldEmployees Msg 213, Level 16, State 1, Line 1 Insert Error: Column name or number of supplied values does not match table definition ولتجنب هذا الخطأ عليك تسمية كل عمود بشكل مستقل. INSERT INTO Employees (FirstName, City, Country) SELECT Name, CityName, CountryName FROM OldEmployees ملاحظة: على أية حال، هنالك بعض الحالات يكون فيها استخدام SELECT مناسبًا، كمثال من أجل الجداول المؤقتة، وهذا يقودنا الى الفقرة التالية. استخدام الجداول المؤقتة Temporary Tables الجداول المؤقتة عادة ما تزيد تعقيد الاستعلام، فإذا كان بالإمكان كتابة شيفرتك بطريقة بسيطة ومباشرة، فأنا أنصحك بتجنب الجداول المؤقتة. لكن إذا كنت تمتلك إجرائية مخزّنة stored procedure مع عمليات تعديل على البيانات لا يمكن إتمامها باستعلام واحد ، يمكنك استخدام الجداول المؤقتة كوسيط لمساعدتك في تحصيل النتائج النهائية. عندما تودّ أن تقوم بعملية ضم جدول ضخم وهنالك قيود على الجدول المذكور، يمكنك تحسين أداء قاعدة البيانات عن طريق ترحيل البيانات الى جدول مؤقت، والقيام بعملية ضم ذلك الجدول، حيث ان الجدول المؤقت يحتوي على سجلات أقل من الجدول الأساسي الضخم، ولذلك ستتم عملية الضم بشكل أسرع. القرار ليس واضح بشكل دائم، ولكن هذا المثال سوف ينبهك للحالات التي يمكنك فيها استخدام الجداول المؤقتة. تخيّل جدول الزبائن بملايين من السجلات، وعليك أن تقوم بعملية الضم لمنطقة محدّدة، يمكنك القيام بذلك عن طريق استخدام SELECT INTO ،والقيام بعملية الضم مع الجدول المؤقت. SELECT * INTO #Temp FROM Customer WHERE RegionID = 5 SELECT r.RegionName, t.Name FROM Region r JOIN #Temp t ON t.RegionID = r.RegionID لاحظ : مطوري SQl أيضًا يتجنبون استخدام SELECT INTO لإنشاء الجداول المؤقتة، لأن هذا الأمر يؤدي إلى قفل قاعدة بيانات tempdb database مما يمنع باقي المستخدمين من إنشاء جداول مؤقتة ، ولحسن الحظ تم التصحيح في النسخة السابعة وما بعدها. وكحل بديل عن استخدام الجداول المؤقتة يمكن استخدام الاستعلام الفرعي كجدول. SELECT r.RegionName, t.Name FROM Region r JOIN (SELECT * FROM Customer WHERE RegionID = 5) AS t ON t.RegionID = r.RegionID لكن انتظر، هنالك مشكلة في الاستعلام الثاني، كما تم شرحه أعلاه، يجب تضمين الأعمدة التي نحتاجها فقط (عدم استخدام * SELECT )، يجب أخذ هذا الأمر بالحسبان SELECT r.RegionName, t.Name FROM Region r JOIN (SELECT Name, RegionID FROM Customer WHERE RegionID = 5) AS t ON t.RegionID = r.RegionID كل هذه الطرق ستعيد نفس البيانات، لكن باستخدام الجداول المؤقتة، وكمثال يمكننا انشاء فهرس في جدول مؤقت لتحسين الأداء. وأخيرًا، عندما تنهي عملك بالجدول المؤقت، قم بحذفه لتنظيف مصادر tempdb بدل أن تنتظر عملية الحذف الاوتوماتيكي (عندما يتم إنهاء اتصالك مع قاعدة البيانات) DROP TABLE #temp هل يتواجد السجل الخاص بي؟ تقنية المعايرة هذه الخاصة ب SQl متعلقة باستخدام التعليمة ()EXISTS إذا كنت تنوي تفحص فيما إذا كان السجل موجودًا استخدم ()EXISTS بدل من ()COUNT. حيث أن ()COUNT يقوم بفحص كامل الجدول، معتبرًا جميع القيم التي تطابق شروطك، بينما ()EXISTS ستوقف الفحص حالما تجد قيمة مطابقة لما تحتاجه. وهذا يفضي إلى أداء أفضل و شفرة أوضح IF (SELECT COUNT(1) FROM EMPLOYEES WHERE FIRSTNAME LIKE '%JOHN%') > 0 PRINT 'YES' مقابل IF EXISTS(SELECT FIRSTNAME FROM EMPLOYEES WHERE FIRSTNAME LIKE '%JOHN%') PRINT 'YES' معايرة قاعدة البيانات (في المكتب) مديري ومطوري قاعدة البيانات غالبًا ما يتجادلون فيما إذا كانت القضايا التي يواجهونها متعلقة أو غير متعلقة بالبيانات. ومن خبرتي الشخصية أقدم هنا مجموعة من النصائح لكليهما كي يتمكنا من العمل بشكل أكثر فاعلية. للمطوّرين: إذا توقف تطبيقك عن العمل فجأة، فقد لايكون الأمر متعلقًا بقاعدة البيانات، كمثال ربما هنالك مشكلة بالشبكة، قم بالتحقق قليلًا قبل أن ترجع السبب إلى مدير قاعدة البيانات. حتى ولو كنت بارعًا في نمذجة بيانات SQl، قم بطلب المساعدة من مدير قاعدة البيانات في المخطط العلائقي relational diagram فلديه الكثير ليقدمه لك. مديري قاعدة البيانات لا يحبون التغيرات السريعة، هذا طبيعي، عليهم تحليل قاعدة البيانات بشكل كامل واكتشاف مدى تأثير أي تغيير من كافة الزوايا. تغيير بسيط في عمود يمكن أن يستغرق اسبوعًا للإنجاز هذا بسبب أن الخطأ قد يعتبر خسارة ضخمة للشركة. كن صبورًا! لا تقم بالطلب من مدير قاعدة بيانات SQL بإجراء تغييرات على البيانات في بيئة العمل وقت التشغيل. إذا كنت تود الوصول الى قاعدة البيانات النشطة، يجب عليك تحمل المسؤولية عن كافة التغيرات. لمديري قاعدة بيانات SQl: إذا كنت لا تحب أن يسألك النّاس بشأن قاعدة البيانات، قم بتزويدهم بلوحة تبيّن الحالة وقت التشغيل. فالمطوّرين عادة لديهم شك بحالة قاعدة البيانات، وهذه اللوحة تساعد في توفير الوقت والجهد للجميع. ساعد المطوّرين في اختبارات ضمان الجودة للبيئة. قم بتسهيل عملية محاكاة عمل المخدّم مع اختبار بسيط على بيانات حقيقية. مما يوفر الوقت بشكل كبير عليك وعليهم. يقضي المطوّرين كل اليوم متعاملين مع أنظمة بمفاهيم عمل تتغير بشكل مستمر. تفهمك لذلك يجعل الأمر أكثر مرونة، ويمكنك من تجاوز بعض القواعد في اللحظات الحرجة. قواعد البيانات تتطور، سيأتي اليوم الذي تحتاج فيه إلى نقل بياناتك الى إصدار جديد، حيث يعتمد المطوّرين على خصائص جديدة في كل إصدار جديد، لذلك خطط و تحسب لعملية النقل بدلًا من أن تقوم برفض هذه التغيرات. ترجمة -وبتصرّف- للمقال SQL-Database-Performance-Tuning-for-Developers لصاحبه Rodrigo Koch حقوق خلفية الصورة البارزة Gradient clouds background محفوظة لـ Vexels
  2. برمجية ووردبريس هي واحدة من أشهر أنظمة إدارة المحتوى مفتوحة المصدر في العالم، وصحيحٌ أنَّ غرضها الأساسي هو إنشاء مدونات، لكنها تطورت على مرّ السنين لتصبح منصةً مرنةً لإنشاء مواقع الويب، ولا نستطيع أن ننكر مدى ثباتها وموثوقيتها التي تطورت خلال خمسة عشر عامًا، لكن ما تزال بعض المشكلات تظهر بين الفينة والأخرى. إذا حاولت فتح موقعك الذي يعتمد على ووردبريس ورأيت رسالةً تُشير إلى خطأ في قواعد البيانات “خطأ في إنشاء اتصال بقاعدة البيانات” (Error Establishing Database Connection)، فمن المرجح أن يكون السبب بين القائمة الآتية: انهارت قاعدة البيانات، ربما بسبب نفاد الذاكرة المتاحة للخادوم معلومات الوصول إلى قاعدة البيانات الموجودة في ضبط ووردبريس غير صحيحة حدث ضرر في جداول قاعدة بيانات ووردبريس لنناقش المشاكل السابقة كلًّا على حدة لنعرف إن كان هو السبب فيما أصاب موقعك، مع ذكر طريقة حلها. المتطلبات المسبقة يفترض هذا الدرس: أنَّك تستعمل ووردبريس على خادوم يمكنك الوصول إلى سطر أوامر وتستطيع تشغيل الأوامر فيه بامتيازات الجذر عبر الأداة sudo. تعمل قاعدة البيانات على خادوم ووردبريس نفسه (وهذا شائع في مواقع ووردبريس المستضافة ذاتيًا، لكنه ليس شائعًا في مواقع ووردبريس المستضافة على استضافة مشتركة). أنَّك تعرف اسم المستخدم الذي يملك وصولًا إلى قاعدة البيانات مع كلمة مروره، واسم قاعدة البيانات الخاصة بورردبريس. يجب أن توفِّر هذه المعلومات عند ضبطك لبرمجية ووردبريس ضبطًا مبدئيًا. الخطوة الأولى: التحقق من الذاكرة المتاحة على الخادوم أوّل خطوة لمعرفة سبب المشكلة هي تسجيل الدخول إلى الخادوم لمعرفة إذا كان سليمًا وأنَّ خدمة MySQL تعمل دون مشاكل. سجِّل دخولك إلى الخادوم عبر SSH، وتذكر أن تضع اسم المستخدم واسم النطاق الخاصين بك في الأمر الآتي: ssh sammy@your_server_ip ملاحظة: إذا كنتَ متأكدًا أنَّ معلومات الاتصال الخاصة بك صحيحة لكنك تواجه مشاكل في تسجيل الدخول، فقد يكون السبب هو نفاد الذاكرة في خادومك أو أنَّه تحت حِملٍ شديد؛ وقد يكون ذلك بسبب كمية كبيرة من البيانات المُرسَلة إلى موقعك، وهذا يُفسِّر سبب الخطأ الذي حدث في ووردبريس… قد تحتاج إلى إعادة تشغيل خادومك قبل أن تتمكن من تسجيل الدخول إليه. بعد أن سجلنا دخولنا بنجاح إلى الخادوم، فيمكننا التأكد أنَّ قواعد MySQL تعمل دون مشاكل: sudo netstat -plt يعرض الأمر netstat معلوماتٍ حول الاتصالات الشبكية في نظامنا، وطلبنا من الأمر السابق أسماء البرامج ‎-p التي تستمع إلى الاتصالات ‎-l على مقابس TCP ‏‎-t؛ عليك الآن البحث عن السطر الذي تُذكر خدمة mysqld فيه: Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 localhost:mysql *:* LISTEN 1958/mysqld tcp 0 0 *:ssh *:* LISTEN 2205/sshd tcp 0 0 localhost:smtp *:* LISTEN 2361/master tcp6 0 0 [::]:http [::]:* LISTEN 16091/apache2 tcp6 0 0 [::]:ssh [::]:* LISTEN 2205/sshd tcp6 0 0 ip6-localhost:smtp [::]:* LISTEN 2361/master إذا كانت مخرجات الأمر السابق عندك مشابهةً لما سبق، فهذا يعني أنَّ خادوم MySQL يعمل ويستمع إلى الاتصالات القادمة؛ أما إذا لم ترَ خدمة MySQL مذكورةً في الناتج، فجرِّب تشغيلها يدويًا، وذلك باستعمال أمرٍ شبيهٍ بالأمر الآتي: sudo systemctl start mysql لاحظ أنَّ بعض توزيعات لينكس (وأشهرها CentOS) تستعمل mysqld بدلًا من mysql للإشارة إلى اسم الخدمة؛ لذا ضع الكلمة الملائمة لنظامك الذي تستعمله. يجب أن تبدأ خدمة MySQL الآن، وأعد تشغيل أمر netstat السابق للتأكد من ذلك، وابحث عن السطر الذي يحتوي على اسم خدمة MySQL. تحتاج قواعد بيانات MySQL وبرمجية ووردبريس إلى قدرٍ لا بأس به من الذاكرة لكي تعمل عملًا سليمًا؛ وإذا انهارت قواعد البيانات بسبب نفاد الذاكرة، فيجب أن نرى دليلًا على ذلك في سجل الأخطاء. لنلقِ نظرة: zgrep -a "allocate memory" /var/log/mysql/error.log* الأمر zgrep سيبحث في ملفات السجل، بما فيها ملفات السجل القديمة والتي ضُغِطَت لتوفير المساحة التخزينية؛ وحددنا في الأمر السابق أننا نبحث في أي سطر يحتوي على العبارة allocate memory في أي ملف error.log*‎ موجود في مجلد ‎/var/log/mysql/‎: 2017-04-11T17:38:22.604644Z 0 [ERROR] InnoDB: Cannot allocate memory for the buffer pool إذا رأيتَ سطرًا أو أكثر يشبه السطر السابق فهذا يعني أنَّ خادوم MySQL قد انهار بسبب عدم كفاية الذاكرة؛ وإذا وجدتَ سطرًا وحيدًا فقط فهذا يعني أنَّ الانهيار عَرَضي بسبب كمية مؤقتة كبيرة من البيانات، أما إذا كانت هنالك عدِّة أسطر تحوي الخطأ نفسه، فهذا يعني أنَّ الذاكرة الحالية لا تكفي خادومك. في كلا الحالتين السابقتين، الحل العملي لهذه المشكلة هو الانتقال إلى خادومٍ تتوافر فيه ذاكرة أكثر، والأمر بسيطٌ جدًا إذا كان خادومك مستضافًا على خدمةٍ سحابية، إذ تستطيع ترقية الخادوم دون انقطاع الخدمة لوقتٍ طويل. إذا لم تجد أيّة مخرجات بعد تنفيذ أمر zgrep السابق، فهذا يعني أنَّ الذاكرة تكفي خادومك، وإن بقي موقعك يُظهِر رسالة الخطأ، فانتقل إلى الخطوة التالية التي نلقي فيها نظرةً على ضبط ووردبريس ونتأكد أنَّ معلومات الدخول إلى قاعدة MySQL صحيحة. الخطوة الثانية: التحقق من معلومات الدخول إلى قاعدة البيانات إذا نقلتَ موقع ووردبريس إلى خادوم جديد أو إلى استضافة أخرى، فقد تحتاج إلى تحديث معلومات الاتصال بقاعدة البيانات، وهذه المعلومات مخزنة في ملف PHP على الخادوم باسم wp-config.php. لنعثر بدايةً على ملف wp-config.php: sudo find / -name "wp-config.php" الأمر السابق يبحث في كل النظام (بدءًا من المجلد الجذر /) عن أي ملف باسم wp-config.php، ثم سيعرض المسار الكامل للملف إن عُثِرَ عليه: /var/www/html/wp-config.php ملاحظة: إذا كنتَ تعلم مكان تثبيت برمجية ووردبريس، فيمكنك الانتقال إلى مسار تثبيتها مباشرةً وتخطي الخطوة السابقة لأنها تستهلك بعض الوقت. استعمل محرِّرك النصي المفضل لتعديل ملف الضبط، سنستعمل محرر nano في الأمر الآتي: sudo nano /var/www/html/wp-config.php ستشاهد أمامك ملفًا نصيًا مليئًا بخيارات الضبط مع بعض التعليقات التي تشرحها. لكنك ستجد قسمًا (في بداية الملف عادةً) فيه معلومات الاتصال إلى قاعدة البيانات: /** The name of the database for WordPress */ define('DB_NAME', 'database_name'); /** MySQL database username */ define('DB_USER', 'database_username'); /** MySQL database password */ define('DB_PASSWORD', 'database_password'); تأكد أن القيم الثلاث السابقة صحيحة بناءً على معلومات الاتصال المسجلة عندك؛ وإذا لم تكن صحيحةً فحدِّثها وفقًا لما تراه مناسبًا، ثم احفظ الملف واخرج من المحرر (بضغط Ctrl+o للحفظ ثم Ctrl+x للخروج، وذلك إذا كنتَ تستعمل محرر nano). حتى لو بدت لك معلومات الاتصال بقاعدة البيانات صحيحةً، فمن المفيد تجربة الاتصال إلى قاعدة البيانات من سطر الأوامر ليطمئن قلبك. انسخ المعلومات المذكورة في ملف الضبط السابق واستعملها في هذا الأمر: mysqlshow -u database_username -p عندما يُطلَب منك إدخال كلمة مرور فألصقها واضغط على زر Enter، وإن ظهر لك خطأ Access denied فهذا يعني أنَّ اسم المستخدم أو كلمة المرور خطأ، وإذا كانا صحيحين فسيعرض الأمر mysqlshow جميع قواعد البيانات التي يملك المستخدم وصولًا إليها: +--------------------+ | Databases | +--------------------+ | information_schema | | database_name | +--------------------+ تأكد أنَّ اسم إحدى قواعد البيانات يطابق تمامًا الاسم المذكور في ملف ضبط ووردبريس؛ وعندئذٍ ستعلم أنَّ ضبطك صحيح وأنَّ ووردبريس يجب أن تكون قادرةً على الاتصال بقاعدة البيانات بنجاح. ادخل إلى موقعك مجددًا لعل رسالة الخطأ تختفي، وإن بقيت موجودةً فلنحاول إصلاح قاعدة البيانات. الخطوة الثالثة: إصلاح قاعدة بيانات ووردبريس قد يحدث عطب في قاعدة بيانات ووردبريس في بعض الأحيان بسبب فشل الترقية أو انهيار قاعدة البيانات أو مشكلة في إحدى الإضافات، وقد تظهر هذه المشكلة على أنها خطأ في الاتصال بقاعدة البيانات، لذا إذا لم تكن المشكلة في خادوم MySQL ولا في ملف الضبط، فجرِّب إصلاح قاعدة البيانات. توفر ووردبريس أداةً مبنيةً داخلها لإصلاح قاعدة البيانات، وهي معطلة افتراضيًا لعدم وجود قيود مفروضة على من يستطيع الوصول إليها مما قد يسبب مشكلةً أمنيةً، لذا سنفعِّل هذه الميزة، ثم نُشغِّل أداة الإصلاح، ثم نعطلها. افتح ملف wp-config.php مرةً أخرى: sudo nano /var/www/html/wp-config.php ألصق ما يلي في سطرٍ جديد: define('WP_ALLOW_REPAIR', true); سيؤدي السطر السابق إلى تفعيل ميزة إصلاح قاعدة البيانات. احفظ الملف وأغلق المحرر النصي، وافتح العنوان الآتي في متصفحك، وتذكر أن تضع اسم النطاق الخاص بموقعك أو عنوان IP التابع له: http://www.example.com/wp-admin/maint/repair.php يجب أن تظهر صفحة الإصلاح: اضغط على زر «Repair Database» ويجب أن تنتقل إلى صفحة النتائج التي تستطع أن ترى فيها التحققات والإصلاحات التي تجريها ووردبريس في الوقت الحقيقي: بعد انتهاء هذه العملية، احرص على تعديل ملف wp-config.php وحذف السطر الذي أضفناه إليه آنفًا. هل لاحظت أيّة إصلاحات أجرتها الأداة؟ جرِّب الدخول إلى موقعك مجددًا وانظر هل اختفت رسالة الخطأ. إذا ظهرت مشاكل لا يمكن حلها فربما ستحتاج إلى استعادة قاعدة البيانات من نسخة احتياطية إذا توافرت عندك. إذا لم يُعثَر على مشاكل في قاعدة البيانات ولم تستطع أن تعرف ما أصل المشكلة، فمن المحتمل أن هنالك مشاكل أخرى لم تنتبه إليها. الخلاصة أغلبية أخطاء “خطأ في إنشاء اتصال بقاعدة البيانات” يمكن حلّها عبر اتباع الخطوات السابقة، لكن مع ذلك هنالك أخطاء أكثر تعقيدًا قد تظهر على شكل خطأ في الاتصال بقاعدة البيانات؛ لذا سأعرض لك قائمةً بالمقالات التي تساعدك في تَتَبُع وإصلاح مسبب المشكلة: أحد المسببات الشائعة للتراسل الكبير لموقع ووردبريس (وبالتالي انخفاض الأداء وحدوث أخطاء) هو هجمات brute-force ، وبالتالي يجب اتخاذ إجراءات للتخفيف من تأثيرها. يمكنك توفير بعض موارد الخادوم باستعمال التخزين المؤقت لصفحات ووردبريس؛ وهنالك عدد كبير من إضافات التخزين المؤقت البسيطة المتوافرة لها. ترجمة –وبتصرّف– للمقال How To Debug the Wordpress “Error Establishing Database Connection”‎ لصاحبه Brian Boucheron. حقوق الصورة البارزة محفوظة لـ Freepik
  3. ماهو MySQL؟ MySQL هو برنامج لإدارة قواعد البيانات Database Management System, DBMS يُساعد مستخدميه في تخزين، تنظيم والعثور على البيانات. ينتشر استخدامُ MySQL في مواقع الويب نظرًا لميزاته والمرونة الّتي يُوفّرها. نهدِف في هذا الدّرس تقديم أساسيّات استخدام MySQL بطريقة مُيَسَّرة وسهلة. كيف يُثَبَّت برنامج MySQL على توزيعتيْ Ubuntu وCentOS؟ يُمكِن تنزيلُ وتثبيتُ MySQL سريعًا عبر برنامج إدارة الحزم الخاصّ بالتّوزيعة. 1- على Ubuntu: sudo apt-get install mysql-server 2- على CentOS: sudo yum install mysql-server /etc/init.d/mysqld start ملحوظة: أثناء تثبيت MySQL سيُطلب منك إدخال ثمّ تأكيد كلمة سرّ للمستخدِم الجذر Root user في MySQL (انتبه إلى أنّ المُستخدم الّذي نتحدّث عنه هنا ليس هو المستخدِم الجذر في الخادوم، بل مستخدم جذر آخر خاصّ بـMySQL). كيف يكون الاتصال بالصدفة Shell الخاصة بـ MySQL؟ يُمكن - بعد التّثبيت - الاتّصال بMySQL عن طريق صَدَفة ولوج خاصّة عبر تنفيذ الأمر التّالي: mysql -u root -p سيُطلب منك إدخال كلمة سر المُستخدم الجذر في MySQL. يُمكنك بعدها البدء في بناء قواعد بيانات في MySQL. ينبغي الانتباه للنّقطتيْن التّاليّتيْن: تنتهي كلّ أوامر MySQL بنقطة-فاصلة إنجليزيّة (;). إن لم تختِم جملةً من أوامر MySQL بنقطة-فاصلة فلن تُتنفّذ هذه الأوامر. تُكتَب أوامرُ MySQL بأحرف كبيرة Uppercase وأسماءُ كلّ من قواعد البيانات، المُستخدمين، الجداول Tables والنّصوص بأحرف صغيرة. هذه النّقطة ليست إجبارية؛ سطرُ أوامر MySQL لا يتأثّر بحالة الأحرف Case insensitive ولكن التّفريق المذكور يجعلُ من التّمييز بين الأوامر وغيرها أكثر سهولة. إنشاء وحذف قاعدة بيانات MySQL يُنظِّم MySQL معلوماتِه في قواعد بيانات تتضمّن كلّ واحدة منها جداول ببيانات مُحدَّدة. يُمكنك عرض قواعد البيانات الموجودة في MySQL عبر الأمر التّالي (يُنفَّذ في صَدَفة MySQL وليس سطر أوامر النّظام): SHOW DATABASES; يجب أن يبدو محتوى الشّاشة لديك مشابِهًا لما يلي: mysql> SHOW DATABASES; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | test | +--------------------+ 4 rows in set (0.01 sec) من اليسير إنشاءُ قاعدة بيانات عن طريق الأمر التّالي(حيثُ database name يُمثّل اسمَ قاعدة البيانات): CREATE DATABASE database name; لإنشاء قاعدة بيانات باسم events مثلًا نُنفّذ الأمر: CREATE DATABASE events; نُعيد عرضَ قواعد البيانات الموجودة في MySQL: mysql> SHOW DATABASES; +--------------------+ | Database | +--------------------+ | information_schema | | events | | mysql | | performance_schema | | test | +--------------------+ 5 rows in set (0.00 sec) نُلاحِظ وجود قاعدة البيانات الّتي أنشأناها للتّو. تُستخدم غالبًا عبارة DROP لحذف الكائنات Objects في MySQL. إذا أردتَ حذفَ قاعدة بيانات فالأمر المناسب هو DROP DATABASE، كما يلي (حيثُ database name اسم قاعدة البيانات المُراد حذفُها): DROP DATABASE database name; استخدام قاعدة بـيانات في MySQL نبدأ بملْء قاعدة البيانات بعدَ إنشائها عبر إضافة معلومات إليها. أولّ خطوة هيّ إنشاء جدول جديد داخل قاعدة البيانات. يتوجّب أوّلًا فتح قاعدة البيانات المُراد استخدامُها عبر الأمر التّالي: USE events; يُمكن -كما فعلنا مع قواعد البيانات- عرضُ الجداول الموجودة في قاعدة البيانات الّتي نستخدمُها الآن: SHOW tables; تظهر، عندَ تنفيذ الأمر السّابق رسالة Empty set (مجموعة خاليّة) دلالةً على عدم وجود جداول في قاعدة البيانات. هذه النّتيجة طبيعيّة جدًّا نظرًا لجِدّة قاعدة البيانات. إنشاء جدول في قاعدة بيانات MySQL نفترِض أنّنا نُخطّط لحَدَث يجمع بعضَ الأصدقاء. سنستخدم MySQL لتتبّع تفاصيل هذا الحدث. نُنشئ جدولًا في MySQL لهذا الغرض (تذكّر أننا نستخدم قاعدة بيانات باسم events أي أنّ الجدول الّذي سنُنشئه سيكون ضمن قاعدة البيانات هذه): CREATE TABLE potluck (id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, name VARCHAR(20), food VARCHAR(30), confirmed CHAR(1), signup_date DATE); نفّذنا عبر الأمر أعلاه الإجراءات التّالية: إنشاء جدول باسم potluck ضمن قاعدة البيانات events. إنشاء خمسة أعمِدة ضمن الجدول potluck. هذه الأعمدة هيّ: id (المُعرِِّف)، name (الاسم)، food (الطّعام)، confirmed (حضور مؤكَّد) و signup date (تاريخ التّسجيل). تطبيق الأمر INT NOT NULL PRIMARY KEY AUTO_INCREMENT للعمود id من أجل إعطاء عدد صحيح (INT في الأمر) أتوماتيكيًّا لكل صف جديد. قصرُ العمود name على عدد محارِف لا يتجاوز العشرين (20)VARCHAR. نفس الشيء بالنّسبة للعمود food الّذي يُمثِّل متعلّقات الطّعام الّتي سيجلبها كل واحد من الأصدقاء. اسم الطّعام مُكوّن من محارِف لا يتجاوز عددها الثّلاثين (30)VARCHAR. تسجيل تأكيد الحضور عبر العمود confirmed المُكوّن من محرف واحد فقط (1)CHAR. عند تأكيد الحضور نكتب Y وإلّا N. حفظ تاريخ التّسجيل عبر العمود signup_date. يطلُب MySQL كتابة التّاريخ على الشّكل yyyy-mm-dd، حيثُ yyyy السّنة مكتوبة على 4 أرقام، وmm الشهر في رقمين وdd اليوم في رقميْن أيضًا. 01-01-2015 تاريخ بصيغة صحيحة. ملحوظة: كلّ من CHAR و VARCHAR يُستخدَم للدّلالة على أن العمود يحوي محارف مع تحديد طول المحتوى، ولكن طول المحتوى من نوع CHAR ثابت، أي أنّه يجب أن يكون مساويًّا للعدد بين قوسيْن؛ في حين أنّ طول المحتوى من نوع VARCHAR متغيِّر والعدد المُذكور هو الطّول الأقصى المسموح به. نُعيد عرض الجداول الموجودة في قاعدة البيانات events: mysql> SHOW TABLES; +------------------+ | Tables_in_events | +------------------+ | potluck | +------------------+ 1 row in set (0.01 sec) نُلاحِظ ظهور الجدول potluck. إن أردتَ عرض تنظيم الجدول potluck فالأمر DESCRIBE يؤدّي هذه الوظيفة: DESCRIBE potluck; انتبِه إلى أنّ أسماء الجداول وقواعد البيانات في MySQL حسّاسة لحالة الأحرف، رغم أنّ سطر الأوامر ليس كذلك. جدول باسم potluck ليس هو نفسُه جدول Potluck أو POTLUCK. mysql>DESCRIBE potluck; +-------------+-------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------------+-------------+------+-----+---------+----------------+ | id | int(11) | NO | PRI | NULL | auto_increment | | name | varchar(20) | YES | | NULL | | | food | varchar(30) | YES | | NULL | | | confirmed | char(1) | YES | | NULL | | | signup_date | date | YES | | NULL | | +-------------+-------------+------+-----+---------+----------------+ 5 rows in set (0.01 sec) إضافة معلومات إلى جدول في MySQL لدينا الآن جدول لتنظيم معلومات الحدَث، بقي ملؤه بالبيانات اللّازمة. استخدِم الأمرَ التّالي لإضافة صف بيانات جديد: INSERT INTO `potluck` (`id`,`name`,`food`,`confirmed`,`signup_date`) VALUES (NULL, "John", "Casserole","Y", '2012-04-11'); يُضيف هذا الأمر مُشاركًا جديدًا في الحدث اسمُه John وسيأتي بطنجرة (Casserole)؛ سجّلَ بتاريخ 2012-04-11 وأكّد حضوره (Y). المُعرّف سيُملأ أوتوماتيكيًّا لذا وضعنا NULL مكان العمود الأول. ستظهر بعد تنفيذ الأمر رسالة شبيهة بالتّاليّة: Query OK, 1 row affected (0.07 sec) نُضيف مشاركين جددًا بتفاصيل مختلفة إلى جدول المُشاركين عبر الأوامر التّاليّة: INSERT INTO `potluck` (`id`,`name`,`food`,`confirmed`,`signup_date`) VALUES (NULL, "Sandy", "Key Lime Tarts","N", '2012-04-14'); INSERT INTO `potluck` (`id`,`name`,`food`,`confirmed`,`signup_date`) VALUES (NULL, "Tom", "BBQ","Y", '2012-04-18'); INSERT INTO `potluck` (`id`,`name`,`food`,`confirmed`,`signup_date`) VALUES (NULL, "Tina", "Salad","Y", '2012-04-10'); لعرض جميع البيانات الموجودة في الجدول نستخدم الأمر أدناه. علامة * تعني معلومات جميع الأعمدة. mysql> SELECT * FROM potluck; +----+-------+----------------+-----------+-------------+ | id | name | food | confirmed | signup_date | +----+-------+----------------+-----------+-------------+ | 1 | John | Casserole | Y | 2012-04-11 | | 2 | Sandy | Key Lime Tarts | N | 2012-04-14 | | 3 | Tom | BBQ | Y | 2012-04-18 | | 4 | Tina | Salad | Y | 2012-04-10 | +----+-------+----------------+-----------+-------------+ 4 rows in set (0.00 sec) إن أردنا الاقتصار على المعلومات الموجودة في بعض الأعمدة وليس كلّها نذكر الأعمدة المعنيّة هنا. مثلا إن أردنا فقط الأسماء والأطعمة ننفّذ الأمر: SELECT name, food FROM potluck; تحديث بيانات موجودة في جدول MySQL يُتيح MySQL إمكانيّة تغيير بيانات موجودة في جدول. في المثال السّابق أضفنا مشارِكةً باسم Sandy. هذم المُشارِكة لم تؤكّد الحضور (قيمة العمود confirmed هي N). أبلغتْنا الآن بأنّها تأكّدت من حضورها. لتحديث عمود confirmed بالنّسبة لـsandy نُنفذ الأمر: UPDATE `potluck` SET `confirmed` = 'Y' WHERE `potluck`.`name` ='Sandy'; يُفهم الأمر أعلاه كما يلي: حدّث بيانات الجدول potluck بضبط عمود confirmed على القيمة Y إذا كانت قيمة العمود name تُساوي Sandy. كما تُلاحظ يوجد شرط للتّحديث وهو الاسم = Sandy. يُمكن أيضًا استخدامُ هذا الأمر لإضافة بيانات إلى خليّة (تقاطع عمود وصفّ) حتى ولو كانت خاويّة. إضافة أوحذف عمود من جدول في MySQL أنشأنا جدولًا ببيانات مُفيدة، ولكن تنقُصُنا معلومة مهمّة: البريد الإلكتروني للمُشترك؛ لذا سنُضيف عمودًا جديدًا نُخزّن فيه هذه المعلومة. ALTER TABLE potluck ADD email VARCHAR(40); يقول هذا الأمر "غيّر الجدول potluck عن طريق إضافة عمود جديد باسم email لا يتجاوز المُحتوى فيه 40 محرفًا". يُضاف هذا العمود افتراضًا في آخر الجدول، إذا كنتَ تُريد وضعَه في مكان مُعيّن يُمكن ذلك كما يلي: ALTER TABLE potluck ADD email VARCHAR(40) AFTER name; أي أنّ العمود الجديد سيُضاف بعد (AFTER) العمود name. بالنّسبة لحذف عمود فهو مُشابه لإضافته: ALTER TABLE potluck DROP email; حذف صفّ من جدول يُمكن إن اقتضت الحاجة حذف صفوف من الجدول عبر الأمر التّالي: DELETE from [table name] where [column name]=[field text]; حيثُ [table name] اسم الجدوَل ، [column name] اسم العمود و[field text] هيّ قيمة العمود في الصّف. نفرض مثلًا أنّنا نُريد حذف Sandy من قائمة المُشاركين: mysql> DELETE from potluck where name='Sandy'; Query OK, 1 row affected (0.00 sec) أي احذَف الصّف الّذي تُساوي فيه قيمةُ عمود الاسم Sandy. في حال وجود أكثر من شخص بهذا الاسم فسيُحذف جميع هؤلاء الأشخاص. نُعيد عرض محتوى الجدول بعد تنفيذ أمر الحذف: mysql> SELECT * FROM potluck; +----+------+-----------+-----------+-------------+ | id | name | food | confirmed | signup_date | +----+------+-----------+-----------+-------------+ | 1 | John | Casserole | Y | 2012-04-11 | | 3 | Tom | BBQ | Y | 2012-04-18 | | 4 | Tina | Salad | Y | 2012-04-10 | +----+------+-----------+-----------+-------------+ 3 rows in set (0.00 sec) لاحِظ عدم تغيّر معرّف أي واحد من المُشتركين المتبقّين. ترجمة -وبتصرّف- للمقال A Basic MySQL Tutorial لصاحبته Etel Sverdlov.
  4. تمّ تطوير Redis في عام 2009، وهو مُخزّن بيانات بنمط المفتاح والقيمة (key value)، وهو مفتوح المصدر، ويُقدّم مرونة في الاستخدام، وكما في جميع نمط قواعد البيانات من نوع NoSQL الّتي اتبعها Redis، أمثال Cassandra, CouchDB, MongoDB، فإن Redis يَسمح للمُستخدِم بتخزين كميات ضخمة من البيانات بدون التقيد المفروض بقواعد البيانات العلائقيّة/الارتباطيّة (relational database)، بالإضافة إلى أنّه قد تمّ مُشابهته ومقارنته مع memcache، فيُمكن استخدامه بعناصره الأساسية كنظام تخبئة. إعداد بيئة ومتطلبات Redis قبل الشروع في تنصيب redis، يجب توفّر بعض المُتطلّبات والّتي من شأنها أنّ تجعل من عمليّة التنصيب أكثر سهولة. سيتمّ في البداية تحديث جميع حزم apt-get: sudo apt-get update سيتمّ بعد ذلك تحميل مُترجم (compiler) باستخدام الحزمة build-essential، والّتي من شأنها المساعدة في تنصيب Redis من المصدر: sudo apt-get install build-essential سيتمّ في الخطوة الأخيرة تحميل الأداة tcl الّتي يَعتمد عليها Redis: sudo apt-get install tcl8.5 تنصيب Redis بعد أنّ تمّ تنصيب المُتطلّبات الأساسيّة، فمن المُمكن الآن الشروع وتنصيب redis، ويُمكن تحديد الإصدار المطلوب أو تحميل الإصدار الأخير والذي سيحمل دائمًا الاسم redis-stable: wget http://download.redis.io/redis-stable.tar.gz يجب بعد ذلك فك ضغط الملفّ والانتقال إليه: tar xvzf redis-stable.tar.gz cd redis-stable يجب الآن المُتابعة مع الأمر make: make ولتنصيب Redis على كامل النّظام، فيُمكن إما نسخ ملفاته من المصدر: sudo cp src/redis-server /usr/local/bin/ sudo cp src/redis-cli /usr/local/bin/ أو تنفيذ الأمر التّالي: sudo make install بعد انتهاء عمليّة التنصيب، من المُستحسن تشغيل Redis كحارس (daemon) في خلفيّة النّظام، ولعمل ذلك يأتي Redis بملفّ برمجي (سكريبت) لهذه المُهمّة. يجب الانتقال إلى المسار utils للوصول إلى هذا الملفّ: cd utils ومن ثم تشغيل الملفّ الخاص بتوزيعات Ubuntu/Debian: sudo ./install_server.sh سيَعرض السكريبت بعض الأسئلة لإتمام عمليّة التهيئة، ولكن يُمكن الاعتماد على الإعداد الافتراضي والاكتفاء بالضغط على Enter، وبعد انتهاء عملية التهيئة سيكون خادم Redis يعمل في الخلفيّة (background). يُمكن تنفيذ الأمر التّالي للوصول إلى قاعدة البيانات Redis: redis-cli يُمكن اختبار Redis كالتّالي: $ redis-cli redis 127.0.0.1:6379> ping PONG redis 127.0.0.1:6379> set mykey somevalue OK redis 127.0.0.1:6379> get mykey "somevalue" أوامر Redis يتمّ إضافة بعض المُعطيات إلى سلسلة رموز (string)، والّتي تُعتبر من أبسط أنواع البيانات (datatype)، باستخدام الأمر التّالي: > SET users:SomeOne "job: SomeJob, email:example@example.com, age: some number " OK تمّ في الأمر السابق استخدام الأمر SET متبوعًا بالمُفتاح users:SomeOne، ومن ثمّ القيمة (value)، وهي سلسلة الرموز (string) نفسها. لا تُؤثر النقطتان (:) الموجودة في المُفتاح على الأمر السابق، ولكن من المُمكن الاستفادة منهما في وصف أوضح للمُفتاح المُراد تعيينه. يُمكن استعراض تفاصيل سلسلة الرموز السابقة باستخدام الأمر GET: GET users:SomeOne "job: SomeJob, email:example@example.com, age: some number " المجالات (Ranges) يتمّ تحديد مجال باستخدام مُعاملين والذين سيُمثلان العنصر الأوّل والعنصر الأخير، فالعنصر الأوّل سيُعتبر 0، وإن كان المُعامل الأخير -1، فإن جميع العناصر حتّى نهاية القائمة سيتمّ شملها، فعلى سبيل المثال، إن كانت قائمة تحتوي على ألوان قوس قزح مُرتبة بالترتيب ROYGBV، فيُمكن استعراضها كما في التّالي: > LRANGE ROYGBV 0 3 1) "red" 2) "orange" 3) "yellow" 4) "green" > LRANGE ROYGBV 0 -1 1) "red" 2) "orange" 3) "yellow" 4) "green" 5) "blue" 6) "violet" > LRANGE ROYGBV 3 -1 1) "green" 2) "blue" 3) "violet" انتهاء الصلاحية (Expiration) لا يُعتبر Redis ذو فائدة في تخزين المعلومات فقط، بل يُمكن استخدامه أيضًا في إنهاء صلاحيتها. يُعيّن الوقت اللازم على المُفتاح أنّ يتواجد خلاله إما بالثواني أو باستخدام طابع الوقت الخاصّ يونكس (Unix Time stamp)، ويتحكم الأمر EXPIRE بالمُدّة الّتي يتوجب على المُفتاح التواجد فيها، ويَعرض الأمر TTL الوقت المُتبقي حتّى انتهاء الصلاحيّة. > SET classified:information "Secret Stuff" OK > EXPIRE classified:information 45 (integer) 1 > TTL classified:information (integer) 31 وفي مُحاولة لاستعادة المعلومات بعد انقضاء مدّة الصلاحيّة، ستكون النتيجة هي nil: > GET classified:information (nil) التزايد أو العلاوة (Incrementing) يَملك Redis القدرة على زيادة سلاسل الرموز (strings) في قاعدة بياناته، مع الانتباه أنّه في حال وجود عمليّة جارية في زيادة قيمةٍ ما، فلا يستطيع أمر آخر التدخل والتعديل، هذا الأمر من شأنه أن يجعل من قاعدة البيانات ثابتة وغير شائبة. > SET population 6 OK > INCRBY population 10 (integer) 16 > INCR population (integer) 17 المداولات (Transactions) يملك Redis القدرة على إنجاز المُداولات (transactions)، والّتي يجب أنّ تخضع إلى: تنفيذ الأوامر بالترتيب، ولن يتمّ مقاطعتها خلال العمليّة من قبل طلبات أُخرى. على المُداولات أنّ تُعالج كلها دفعةً واحدة. تبدأ المُداولات بالأمر MULTI وبعد ذلك لتنفيذها يتمّ استخدام الأمر EXEC. سيتمّ الخروج من المُداولة، عند أي مُقاطعة للعمليّة، وسيواجه Redis خطًا سيوقفه من إعادة التشغيل حتّى تنفيذ الأمر edis-check-aof ليتمّ التراجع عن المُداولة الجزئية الّتي تمّت بالفعل قبل حدوث الخطأ وحذفها. سيَتمكّن الخادم بعد ذلك من إعادة التشغيل. > MULTI OK > SET population 6 QUEUED > INCRBY population 10 QUEUED > INCR population QUEUED > EXEC 1) OK 2) (integer) 16 3) (integer) 17 أنواع البيانات في Redis يَملك Redis خمسة أنواع من البيانات: Strings Sets Sorted Sets Lists Hashes سلاسل الرموز (Strings) تُعتبر سلاسل الرموز جوهر وأساس الأنواع في Redis الأوامر التّالية هي الأوامر الشائعة مع سلاسل الرموز: SET: يُعيّن قيمة إلى مُفتاح. GET: يجلب قيمة من مُفتاح. DEL: حذف مُفتاح وقيمته. INCR: زيادة قيمة مُفتاح. INCRBY: زيادة قيمة مُفتاح بقيم مُحدّدة. EXPIRE: الوقت اللازم على المُفتاح التواجد به، ويُعيّن بالثواني. تُستخدم سلاسل الرموز في تخزين الكائنات (objects): > SET newkey "the redis string begins" OK > GET newkey "the redis string begins" المجموعات (Sets) يُمكن الجمع بين سلاسل الرموز (strings)، ولذلك يُمكن استخدام مجموعات Redis، والّتي يُمكن القول عنها أنها مجموعة من سلاسل الرموز غير المُرتبة. بعض الأوامر الشائعة مع المجموعات: SADD: إضافة عنصر أو عناصر إلى مجموعة. SMEMBERS: جلب جميع العناصر المُعيّنة. SINTER: إيجاد تقاطع أكثر من مجموعة. SISMEMBER: التأكّد من وجود قيمة في مجموعة. SRANDMEMBER: جلب عنصر عشوائي. يُستفاد من المجموعات في Redis في العديد من الحالات، ولأن كل عنصر من مجموعة هو فريد، فإن إضافة عنصر إلى المجموعة لا يتطلّب عمليّة “افحص قبل الإضافة”، بدلًا من ذلك، فإن المجموعة ستتأكّد فيما إذا كان العنصر مكرّرًا أم لا، وذلك عند أي تنفيذ للأمر SADD: > SADD colors red (integer) 1 redis 127.0.0.1:6379> SADD colors orange (integer) 1 redis 127.0.0.1:6379> SADD colors yellow (integer) 1 redis 127.0.0.1:6379> SADD colors orange (integer) 0 redis 127.0.0.1:6379> SMEMBERS colors 1) "red" 2) "yellow" 3) "orange" يُستفاد من المجموعات بشكل خاصّ في فحص وضبط عناوين IPs في حال أنها فريدة لزوار صفحة ما، أو مثلًا في استخلاص عناصر بشكل عشوائي بالأمر SRANDMEMBER. المجموعات المرتبة (Sorted Sets) إن المجموعات المُرتبة هي اسمٌ على مُسمّى، فهي مجموعة من سلاسل الرموز (strings) مُرتبطة مع رقم مع ترتيب، وهو بشكلٍ افتراضيّ من الأصغر إلى الأكبر. يَعمل هذا النوع من البيانات بشكل مُلائم جدًا مع المجالات (ranges)، وبسبب التّرتيب الخاصّ به، فإن إضافة وحذف وتحديث القيم تتمّ بسرعة ملحوظة. بعض الأوامر الشائعة مع المجموعات المُرتّبة: ZADD: إضافة عناصر إلى مجموعة مُرتّبة. ZRANGE: عرض عناصر مجموعة مُرتّبة. ZREVRANGE: عرض عناصر مجموعة مُرتّبة بشكل عكسي. ZREM: إزالة عناصر من مجموعة مُرتّبة. يُمكن إنشاء مجموعة مُرتّبة كما في المثال التّالي، وهو لمساحة بعض البلدان، فعلى الرغم من تعيينها بشكل عشوائي، فإن استعراضها يَكون على التّرتيب: > ZADD countries 9 Tuvalu (integer) 1 > ZADD countries 62 Liechtenstein (integer) 1 > ZADD countries .7 Monaco (integer) 1 > ZADD countries .2 VaticanCity (integer) 1 > ZADD countries 107 Seychelles (integer) 1 redis 127.0.0.1:6379> ZRANGE countries 0 -1 1) "VaticanCity" 2) "Monaco" 3) "Tuvalu" 4) "Liechtenstein" 5) "Seychelles" القوائم (Lists) تُعتبر القوائم في Redis مجموعة من القيم المُرتّبة، وبالتّالي فهي عكس المجموعات (Sets)، والّتي هي غير مُرتّبة، فيُمكن إضافة عناصر إلى بداية ونهاية قائمة، حتّى بوجود ملايين العناصر داخل القائمة، وبسرعة كبيرة جدًا. الأوامر الأكثر شيوعًا مع القوائم: LPUSH: إضافة قيمة في بداية قائمة. RPUSH: إضافة قيمة في نهاية قائمة. LPOP: جلب وإزالة العنصر الأوّل في قائمة. LREM: إزالة العناصر من قائمة. LRANGE: جلب مجال من العناصر من قائمة. LTRIM: تعديل قائمة بترك عناصر مُحدّدة من مجال. أمثلة: > RPUSH lunch.provider alice (integer) 1 > RPUSH lunch.provider bob (integer) 2 > RPUSH lunch.provider carol (integer) 3 > RPUSH lunch.provider don (integer) 4 > RPUSH lunch.provider emily (integer) 5 عند الرغبة بالدفع (push) إلى واجهة صف الانتظار (queue)، فمن المُمكن استخدام الأمر LPUSH: LPUSH lunch.provider zoe (integer) 6 يُمكن استخدام الأمر LRANGE لاستعراض عناصر القائمة جميعًا: LRANGE lunch.provider 0 -1 1) "zoe" 2) "alice" 3) "bob" 4) "carol" 5) "don" 6) "emily" تُستخدم القوائم في مُعظم الأحيان لإنشاء خط زمني للأحداث، أو في الحفاظ على مجموعة مُحدودة من العناصر المبعثرات (Hashes) تُعتبر المبَعثرات في Redis من الأدوات المُفيدة في تمثيل الكائنات (objects) ذو العديد من الحقول (fields)، فهي مُعدّة لتخزين عدد هائل من الحقول في حجم صغير، وتستطيع البَعثرة تخزين أكثر من أربعة مليارات من أزواج قيم الحقول (field-value). بعض أوامر البعثرة الأكثر شيوعًا في Redis: HMSET: تعيين قيم بعثرة مُتعدّدة. HSET: تعيين حقل البعثرة بقيمة سلسلة رموز (string). HGET: جلب قيمة حقل البعثرة. HMGET: جلب جميع القيم من حقول البعثرة المعطاة. HGETALL: جلب جميع القيم لبعثرة ما. تُستخدم البَعثرة في وصف حساب المُستخدِم: > HMSET user:1 username someuser password 4bAc0s email someuser@example.com OK > HGETALL user:1 1) "username" 2) "jsmith" 3) "password" 4) "4bAc0s" 5) "email" 6) "jsmith@gmail.com" يتمّ استخدام الأمر HMGET للبحث عن معلومة مُحدّدة، وعرض القيم للحقول المطلوبة فقط. > HMGET user:1 username email 1) "someuser" someuser@example.com الختام انتشر Redis بسرعة كبيرة، واكتسب شهرةً واسعة بين المواقع أمثال: Github, Flickr, Disqus، وغيرها من المواقع، وذلك لتوافقه مع مُعظم لغات البرمجة، فهو بالفعل تقنية مُفيدة يُنصح بالاعتماد عليها وتجربتها. ترجمة -وبتصرّف- للمقال How To Install and Use Redis لصاحبته Etel Sverdlov.
  5. يوفر تهجير قواعد البيانات Database migration في Laravel آليات لإنشاء الجداول Tablesوالتعديل عليها بغض النظر نظام إدارة قواعد البيانات المستخدم. يعني هذا أنك لن تضطر للاهتمام بالاختلافات بين نظم إدارة قواعد البيانات في صياغة أوامر SQL. يمكّن التهجير أيضا من التراجع والعودة إلى ما كانت عليه قاعدة البيانات قبل آخر التعديلات. هذا الدرس جزء من سلسلة تعلم Laravel والتي تنتهج مبدأ "أفضل وسيلة للتعلم هي الممارسة"، حيث ستكون ممارستنا عبارة عن إنشاء تطبيق ويب للتسوق مع ميزة سلة المشتريات. يتكون فهرس السلسلة من التالي: مدخل إلى Laravel 5.تثبيت Laravel وإعداده على كلّ من Windows وUbuntu.أساسيات بناء تطبيق باستخدام Laravel.إنشاء روابط محسنة لمحركات البحث (SEO) في إطار عمل Laravel.نظام Blade للقوالب.تهجير قواعد البيانات في Laravel. (هذا الدرس)استخدام Eloquent ORM لإدخال البيانات في قاعدة البيانات، تحديثها أو حذفها.إنشاء سلة مشتريات في Laravel.الاستيثاق في Laravel.إنشاء واجهة لبرمجة التطبيقات API في Laravel.إنشاء مدوّنة باستخدام Laravel.استخدام AngularJS واجهةً أمامية Front end لتطبيق Laravel.الدوّال المساعدة المخصّصة في Laravel.استخدام مكتبة Faker في تطبيق Laravel لتوليد بيانات وهمية قصدَ الاختبار. يمكن النظر إلى تهجير قواعد البيانات كما لو كان نظام إدارة نسخ خاص بقواعد البيانات، إذ يتيح لفريق العمل سهولة تغيير مخطّط Schema البيانات وتشاركه. نكمل في هذا الدرس اعتمادا على ما أنشأناه في الدروس السابقة من السلسلة. يغطي الدرس المواضيع التالية: متطلبات التهجير.أمر Artisan لتهجير قواعد البيانات.بنية التهجير.إنشاء جدول بآلية التهجير.استخدام آلية التهجير للتراجع Rollback عن التعديلات.بذر قواعد البيانات Database seeding.بنية قاعدة البيانات الخاصة بمشروع Larashop.ملفات التهجير لقاعدة بيانات Larashop.متطلبات التهجيريجب أولا إنشاء قاعدة بيانات في نظام إدارة قواعد البيانات المستخدم (MySQL في حالتنا) وإعداد معطيات الاتصال بها في Laravel ولدى أداة سطر الأوامر Artisan. إنشاء قاعدة بياناتنفذ الأمر التالي في سطر أوامر MySQL أو استخدم التطبيق المفضّل لديك (PHPMyAdmin مثلا) لإنشاء قاعدة بيانات larashop: CREATE DATABASE `larashop`;إعداد Laravel للاتصال بقاعدة البياناتأعددنا Laravel في الدرس الأول من هذه السلسلة للاتصال بقاعدة بيانات باسم larashop. في ما يلي تذكير بخطوات الإعداد. افتح الملف config/database.php واعثر على الأسطُر التالية: 'mysql' => [ 'driver' => 'mysql', 'host' => env('DB_HOST', 'localhost'), 'database' => env('DB_DATABASE', 'forge'), 'username' => env('DB_USERNAME', 'forge'), 'password' => env('DB_PASSWORD', ''), 'charset' => 'utf8', 'collation' => 'utf8_unicode_ci', 'prefix' => '', 'strict' => false, ],حدّث القيم التالية لتوافق إعدادات MySQL لديك: 'database' => env('DB_DATABASE', 'larashop'), 'username' => env('DB_USERNAME', 'root'), 'password' => env('DB_PASSWORD', 'melody'), إعداد معطيات اتصال Artisan بقاعدة البياناتيواجه الكثير من المطورين رسالة الخطأ التالية عند العمل على تهجير قواعد البيانات باستخدام أداة Artisan: Access denied for user 'homestead'@' localhost' (using password: YES)ستظهر الرسالة أعلاه حتى ولو كانت معطيات الاتصال في الملف configuration/database.php صحيحة. يعود السبب في ذلك إلى أن Artisan يستخدم المعطيات الموجودة في الملف env.. الحل هو إذن تحرير الملف env. الواقع في مجلد التطبيق، ستجد ما يلي: APP_ENV=local APP_DEBUG=true APP_KEY=aqk5XHULL8TZ8t6pXE43o7MBSFchfgy2 DB_HOST=localhost DB_DATABASE=homestead DB_USERNAME=homestead DB_PASSWORD=secret CACHE_DRIVER=file SESSION_DRIVER=file QUEUE_DRIVER=sync MAIL_DRIVER=smtp MAIL_HOST=mailtrap.io MAIL_PORT=2525 MAIL_USERNAME=null MAIL_PASSWORD=null MAIL_ENCRYPTION=null حدث المتغيرات التالية: DB_HOST=localhost DB_DATABASE=homestead DB_USERNAME=homestead DB_PASSWORD=secretلتصبح: DB_HOST=localhost DB_DATABASE=larashop DB_USERNAME=root DB_PASSWORD=melody احرص على موافقة اسم قاعدة البيانات، اسم المستخدم وكلمة مروره للمعطيات لديك. احفظ التعديلات. تهجير قواعد البيانات بأداة Artisanينشئ أمر artisan ملفا على المسار database/migrations لكل عملية تهجير. يمكن تغيير المسار الخاص بحفظ ملفات التهجير إن أردت ولكننا هنا سنكتفي بالمسار المبدئي. ننفذ الأمر التالي لإنشاء أول ملف تهجير: php artisan make:migration create_drinks_tableتظهر رسالة باسم ملف التهجير الجديد. اخترنا اسم create_drinks_table للدلالة على أن التهجير ينشئ جدولا باسم drinks في قاعدة البيانات. نتيجة الأمر هي إنشاء ملف للتهجير بنفس الاسم الذي أعطيناه مع إضافة ختم زمني قبله، مثلا: 2015_12_21_215845_create_drinks_table.phpبنية ملف التهجيرندرس الآن محتوى ملف التهجير الذي أنشأناه للتو. افتح الملف التالي لرؤية محتواه (انتبه إلى أن اسم الملف يبدأ بختم زمني للحظة إنشائه): database/migrations/2015_12_21_215845_create_drinks_table.phpنجد ما يلي: <?php use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; class CreateDrinksTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { // } /** * Reverse the migrations. * * @return void */ public function down() { // } }يعرف ملف التهجير صنفا جديدا باسم CreateDrinksTable يمدد الصنف Migration: CreateDrinksTable extends Migrationداخل الصنف CreateDrinksTable توجد دالة باسم up. تنفّذ تعليمات الدالة up عند تشغيل التهجير. توجد أيضا دالة باسم down في الصنف CreateDrinksTable. تنفذ تعليمات الدالة down عند التراجع عن تغييراتِ تهجير.ملف تهجير لإنشاء جدول بقاعدة البياناتليمكن إنشاء جدول في قاعدة البيانات فجيب تعريف حقوله في ملف التهجير. نعيد فتح ملف التهجير السابق ونعدله ليصبح محتواه التالي : <?php use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; class CreateDrinksTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('drinks', function (Blueprint $table) { $table->increments('id'); $table->string('name',75)->unique(); $table->text('comments')->nullable(); $table->integer('rating'); $table->date('juice_date'); $table->timestamps(); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists('drinks'); } }في الدالة up: نستدعي الدالة create المعرَّفة في الصنف Schema ونمرر لها معطيين، الأول اسم الجدول الذي نريد إنشاءه drinks، والمعطى الثاني دالة غير محدّدة الاسم تعرّف حقول الجدول. نستخدم كائنا من صنف Blueprint لتعريف الجدول.نعرف أول حقل من الجدول وهو الحقل id. تعرف الدالة increments التابعة للصنف Blueprint عددا طبيعيا (عدد صحيح إشارته موجبة) يزداد تلقائيّا مع كل إدخال للبيانات في الجدول.الحقل الثاني هو حقل الاسم name، الذي نعرفه بالدالة string. تنشئ الدالة stringحقلا من سلسلة محارف مع تحديد طول السلسلة (75 في المثال). نعلّم الحقل name بالدالة unique \لجعله وحيدا وهو ما يعني أنه لا يمكن لتسجيلتين في الجدول أن تحويا نفس القيمة بالنسبة لهذا الحقل.الحقل الثالث comments نصي، وتستخدم الدالة text لتعريفه. نتيح إمكانية ألا يحوي الحقل بيانات باستخدام الدالة nullable.الحقل الرابع rating للتقيمات. نستخدم الدالة integer للإشارة إلى أنه عدد صحيح.ثم نضيف حقلا لتخزين تاريخ المشروب juice_date ونستخدم الدالة date لهذا الغرض.تُستخدم الدالة timestamps لإضافة حقلين هما created_at وupdated_at في الجدول تلقائيا. الحقلان عبارة عن ختم زمني ل، على التوالي، تاريخ إضافة التسجيلة إلى قاعدة البيانات وتاريخ آخر تحديث عليها.في الدالة down نحذف الجدول drinks من قاعدة البيانات في حالة وجوده.ننفذ بعد حفظ ملف التهجير الأمر التالي: php artisan migrateستظهر مخرجات في سطر الأوامر على النحو التالي: Migration table created successfully. Migrated: 2014_10_12_000000_create_users_table Migrated: 2014_10_12_100000_create_password_resets_table Migrated: 2015_12_21_215845_create_drinks_tableإن نظرت في جداول قاعدة البيانات الآن فستجد التالي: ستلاحظ وجود أربعة جداول من بينها جدول drinks. الجداول الأخرى أنشأها Laravel لأن ملفات تهجيرها تأتي مبدئيا مع Laravel. التراجع عن التعديلاتيوفر التهجير إمكانية التراجع عن تعديلاته والعودة إلى حالة قاعدة البيانات قبل تنفيذه. أنشأنا في الفقرة السابقة جداول في قاعدة البيانات، ننفذ الأمر التالي للتراجع عن ذلك: php artisan migrate:rollbackتظهر الرسائل التالية: Rolled back: 2015_12_21_215845_create_drinks_table Rolled back: 2014_10_12_100000_create_password_resets_table Rolled back: 2014_10_12_000000_create_users_tableإن أعدت التحقق في MySQL سترى أن الجدول drinks لم يعد موجودا. نعيد إنشاء الجدول بتنفيذ التهجير مرة أخرى: php artisan migrateتمكن ملاحظة أن تنفيذ التهجير يكون بالتسلسل الزمني التصاعدي لتاريخ إنشاء ملفات التهجير (من الأقدم إلى الأحدث)، في ما يكون التراجع بتنفيذ ملفات التهجير حسب التسلسل الزمني التنازلي (من الأحدث إلى الأقدم). إدارة جداول البيانات في Laravel باستخدام التهجيرسنرى في هذه الفقرة كيفية استخدام التهجير للقيام بأشغال شائعة على جداول قواعد البيانات. إدراج بياناتسنرى الآن كيفية استخدام التهجير لإدراج بيانات في جدول أثناء إنشائه. ننشئ جدولا بالموظفين employees وندرج فيه 33 تسجيلة بالاعتماد على مكتبة Faker (سنخصص درسا لتفصيل استخدام Faker). نفذ الأمر التالي لإنشاء ملف تهجير لجدول employees: php artisan make:migration employeesنفتح الملف المنشأ للتو ونضيف الشفرة التالية: <?php use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; class Employees extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('employees', function (Blueprint $table) { $table->increments('id'); $table->string('name'); $table->string('email')->unique(); $table->string('contact_number'); $table->timestamps(); }); $faker = Faker\Factory::create(); $limit = 33; for ($i = 0; $i < $limit; $i++) { DB::table('employees')->insert([ //, 'name' => $faker->name, 'email' => $faker->unique()->email, 'contact_number' => $faker->phoneNumber, ]); } } /** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists('employees'); } } ننشئ كائنا من صنف Faker بالتعليمة $faker = Faker\Factory::create();نحدد عدد التسجيلات التي نود إدراجها: limit$. نستخدم حلقة for التكرارية لإضافة التسجيلات إلى الجدول. تولد التعليمة faker->name$ اسما وهميّا، faker->unique()->email$ اسم بريد وحيد وfaker->phoneNumber$ رقم هاتف وهميا.الأمر التالي ينفذ التهجير: php artisan migrateتظهر الرسالة التالية دلالة على تهجير الجدول employees: Migrated: 2015_12_21_225233_employees إن بحثت الآن عن محتوى الجدول employees، مثلا بتنفيذ الاستعلام التالي في سطر أوامر MySQL: SELECT * FROM employees;ستحصُل على أسماء الموظفين، عناوينهم البريدية وأرقام هواتفهم. نتراجع عن إنشاء الجدول employees بتنفيذ الأمر: php artisan migrate:rollbackتظهر رسالة دلالة على التراجع عن إنشاء الجدول. نفتح ملف التهجير للتعديل عليه ثم نضع الشفرة الخاصة بإدراج بيانات وهمية بين علامتي تعليق، هكذا: /* $faker = Faker\Factory::create(); $limit = 33; for ($i = 0; $i < $limit; $i++) { DB::table('employees')->insert([ //, 'name' => $faker->name, 'email' => $faker->unique()->email, 'contact_number' => $faker->phoneNumber, ]); } */احفظ ملف التهجير ثم نفذ الأمر: php artisan migrateسيُنشأ جدول employees من جديد ولكن هذه المرة دون إدراج تسجيلات في الجدول. إضافة عمود إلى جدول أو حذفه منهنفرض أننا نود إضافة عمود جديد gender لتخزين جنس الموظّف، مباشرة بعد العمود contact_number. ننفذ الأمر التالي لإنشاء ملف تهجير باسم add_gender_to_employees مع تحديد الجدول الذي نريد العمل عليه وهو employees: php artisan make:migration add_gender_to_employees --table=employeesتشير التعليمة table=employees-- إلى أننا نريد العمل على الجدول employees الموجود في قاعدة البيانات. افتح ملف التهجير المنشأ بعد الأمر السابق، وعدله ليصبح على النحو التالي: <?php use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; class AddGenderToEmployees extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::table('employees', function (Blueprint $table) { $table->string('gender')->after('contact_number'); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::table('employees', function (Blueprint $table) { $table->dropColumn('gender'); }); } } في الدالة up أضفنا حقلا جديدا من نوع string (سلسلة محارف) وحددنا مكانه بأنه بعد العمود contact_number.في الدالة down نحذف الحقل gender.الآن عند تنفيذ أمر التهجير php artisan migrate ستلاحظ إضافة عمود جديد باسم gender بعد عمود contact_number. تغيير نوع عموديحتاج تغيير نوع العمود لتثبيت حزمة Doctrine Database Abstract Layer, DBAL. تُستخدم هذه الحزمة لتهجيرات التعديل على الجداول Alter table. سنستخدم أداة إدارة الاعتماديات Composer لتثبيت الحزمة. افتح ملف composer.json الذي يوجد في مجلد التطبيق. ابحث عن مقطع require: "require": { "php": ">=5.5.9", "laravel/framework": "5.2.*" },توجد في هذا المقطع حزم المكتبات التي يحتاجها تطبيقنا. حتى الآن توجد حزمتان فقط هما php وlaravel. يشير الجزء الأول (قبل النقطتين) إلى اسم الحزمة، في ما يشير الثاني لإصدارها. نضيف حزمة dbal` إلى هذه الاعتماديات، وذلك على النجو التالي: "require": { "php": ">=5.5.9", "laravel/framework": "5.2.*", "doctrine/dbal": "v2.4.2" }, لاحظ الفاصلة اللاتينية التي أضفناها بعد حزمة Laravel. نفذ الأمر التالي لتحديث المشروع: composer updateعند إنشاء العمود gender لم نحدد طول الحقل، أي أنه سيأخذ الطول المبدئي للحقول من نوع string وهو255 محرفا. ننشئ ملف تهجير جديدا لتعديل طول الحقل ليصبح 5 كحد أقصى. نعدل الملف على النحو التالي: php artisan make:migration modify_gender_in_employees --table=employeesقبول فراغ الحقول في الجدوليفترض Laravel عند إنشاء الحقول أنها لا تقبل فراغ القيمة، أي أنه يجب ذكر قيمة للحقل عند إدراج تسجيلات في الجدول. يمكننا تغيير هذا الإعداد المبدئي وجعل قيمة حقل ما اختيارية. سنأخذ الحقل gender للتمثيل به. ننشئ ملفا للتهجير: php artisan make:migration make_gender_null_in_employees --table=employeesثم نعدله على النحو التالي: <?php use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; class MakeGenderNullInEmployees extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::table('employees', function (Blueprint $table) { $table->string('gender', 5)->nullable()->change(); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::table('employees', function (Blueprint $table) { $table->string('gender', 5)->change(); }); } } تجعل الدالة nullable الحقل gender يقبل قيما فارغة.php artisan migrate إضافة مفتاح خارجي Foreign keyنصنف موظفينا حسب القسم الذي يعملون فيه. ننشئ جدولا للأقسام depts ثم نضيف مفتاحا خاريجا في جدول الموظفين employees. الأمر أدناه ينشئ ملف تهجير لجدول الأقسام: php artisan make:migration deptsعدل ملف التهجير: <?php use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; class Depts extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('depts', function (Blueprint $table) { $table->increments('id'); $table->string('name'); $table->timestamps(); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists('depts'); } }ثم ننفذ أمر التهجير لإنشاء الجدول: php artisan migrateيُشترط لتصح علاقة عبر مفتاح خارجي بين جدولين أن يكون المفتاح الخارجي والمفتاح الرئيس Primary key متطابقين في النوع. استخدمنا في تعريف المفتاح الرئيس idضمن الجدول depts دالة increments التي تعطي النوع عددا طبيعيا من عشرة أرقام ;(unsigned integer INT(10 وهو ما يعني أننا سنعطي نفس النوع للمفتاح الخارجي الذي سننشئه في الجدول employees. الفرق أن المفتاح الخارجي لا يزداد تلقائيا لذا سنستخدم الدالة unsignedInteger التي لها نفس مفعول increments من حيث نوع الحقل وطوله، مع فرق أنها لا تضيف الازدياد التلقائي. ملحوظة: حتى تمكن إضافة مفتاح خارجي في الجدول employees يجب أن يكون الجدول فارغا (بدون تسجيلات). لهذا السبب علقنا في فقرة ماضية الشفرة الخاصة بـFaker. نفذ الأمر التالي لإنشاء ملف تهجير لإضافة حقل المفتاح الخارجي dept_id إلى الجدول employees: php artisan make:migration add_dept_id_in_employees --table=employeesثم نعدل ملف التهجير: <?php use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; class AddDeptIdInEmployees extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::table('employees', function (Blueprint $table) { $table-> unsignedInteger ('dept_id')->after('gender'); $table->foreign('dept_id') ->references('id')->on('depts') ->onDelete('cascade'); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::table('employees', function (Blueprint $table) { $table->dropColumn('dept_id'); }); } }ثم ننفذ التهجير: php artisan migrate بذر قواعد البياناتيشير مصطلح البذر Seeding إلى عملية إضافة بيانات وهمية لأغراض الاختبار في قواعد البيانات. نطبق هذا الإجراء على جدول drinks الذي أنشأناه في أول الدرس. نفذ الأمر التالي لإنشاء ملف للبذر: php artisan make:seeder DrinksTableSeederينشئ الأمر ملفا باسم DrinksTableSeeder.php على المسار database/seeds. افتح الملف: <?php use Illuminate\Database\Seeder; class DrinksTableSeeder extends Seeder { /** * Run the database seeds. * * @return void */ public function run() { // } } يمدد الصنف DrinksTableSeeder الصنف Seeder ويعرّف الدالة run التي تُنفّذ عند تشغيل أمر البذر في Artisan. عدل الملف ليصبح محتواه التالي: <?php use Illuminate\Database\Seeder; class DrinksTableSeeder extends Seeder { /** * Run the database seeds. * * @return void */ public function run() { DB::table('drinks')->insert([ 'name' => 'Orange Juice', 'comments' => 'Rich in C vitamin', 'rating' => 9, 'juice_date' => '2015-12-20', ]); } أضفنا في الدالة run أمر إدراج في جدول البيانات drinks ومررنا مصفوفة توافق عناصرها حقول الجدول مع تحديد قيم عناصر المصفوفة. ننفذ الأمر أمر البذر لإضافة التسجيلة أعلاه إلى الجدول: php artisan db:seed --class=DrinksTableSeederنمرر لأمر البذر php artisan db::seed اسم الملف المراد تنفيذه. الآن عند التحقق نجد في جدول قاعدة البيانات التسجيلة التالية: قاعدة البيانات الخاصة بمشروع Larashopتعرفنا في الفقرات الماضية على أساسيات التهجير في Laravel. سنجعل هذه المعرفة موضع التطبيق لإنشاء قاعدة بيانات لمشروع Larashop. ستشنرك جميع الجداول في الحقول التالية التي أنشأناها لأغراض الفحص والتدقيق. التسلسلالحقلنوع البياناتالوصف1created_at Timestamp ختم زمني لتاريخ إدراج التسجيلة2updated_at Timestamp ختم زمني لتاريخ تحديث التسجيلة3created_at_ip (Varchar(45 عنوان IP المستخدم لإدراج التسجيلة4updated_at_ip (Varchar(45 عنوان IP المستخدم لتحديث التسجيلةجدول منشورات المدونةالتسلسلالحقلنوع البياناتالوصف1id INT مفتاح رئيس (AUTOINCREMENT) عدد طبيعي يزداد تلقائيا2url (Varchar(255 رابط الصفحة3title (Varchar(140 عنوان الصفحة4description (Varchar(170 وصف يظهر في محركات البحث5content Text محتوى الصفحة أو المنشور 6conblogtent (Tinyint(1 يحدد ما إذا كان المنشور صفحةجدول التصنيفاتالتسلسلالحقلنوع البياناتالوصف1id INT مفتاح رئيس (AUTOINCREMENT) عدد طبيعي يزداد تلقائيا2name (Varchar(255 اسم التصنيفجدول العلامات التجاريةالتسلسلالحقلنوع البياناتالوصف1id INT مفتاح رئيس (AUTOINCREMENT) عدد طبيعي يزداد تلقائيا2name (Varchar(255 اسم العلامة التجاريةجدول المنتجاتلكل منتج تصنيف وعلامة تجارية وحيدين. التسلسلالحقلنوع البياناتالوصف1id INT مفتاح رئيس (AUTOINCREMENT) عدد طبيعي يزداد تلقائيا2name (Varchar(255 اسم المنتج3title (Varchar(140 عنوان المنتج4description (Varchar(500 عنوان المنتج5price int ثمن المنتج6category_id int معرف تصنيف المنتج7brand_id int معرف العلامة التجارية للمنتجملفات التهجير لجداول قاعدة بيانات المشروعسننشئ في هذه الفقرة ملفات تهجير لجداول البيانات المذكورة أعلاه؛ سنضيف أيضا بعض البيانات الوهمية إلى الجداول باستخدام آلية البذر التي تعرفنا عليها سابقا. توليد ملفات التهجيرافتح سطر الأوامر ونفذ الأوامر التالية لتوليد ملفات الجداول: جدول منشورات المدونة: php artisan make:migration create_posts_table جدول تصنيفات المنتجات php artisan make:migration create_categories_tableجدول العلامات التجارية للمنتجات php artisan make:migration create_brands_tableجدول المنتجات php artisan make:migration create_products_tableتحرير ملفات التهجيرننتقل لتحرير كل ملف من ملفات التهجير. جدول منشورات المدونة <?php use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; class CreatePostsTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('posts', function (Blueprint $table) { $table->increments('id'); $table->string('url', 255)->unique(); $table->string('title', 140); $table->string('description', 170); $table->text('content'); $table->boolean('blog'); $table->timestamps(); $table->string('created_at_ip'); $table->string('updated_at_ip'); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::drop('posts'); } } جدول التصنيفات <?php use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; class CreateCategoriesTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('categories', function (Blueprint $table) { $table->increments('id'); $table->string('name', 255)->unique(); $table->timestamps(); $table->string('created_at_ip'); $table->string('updated_at_ip'); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::drop('categories'); } } جدول العلامات التجارية <?php use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; class CreateBrandsTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('brands', function (Blueprint $table) { $table->increments('id'); $table->string('name', 255)->unique(); $table->timestamps(); $table->string('created_at_ip'); $table->string('updated_at_ip'); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::drop('brands'); } } جدول المنتجات <?php use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; class CreateProductsTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('products', function (Blueprint $table) { $table->increments('id'); $table->string('name', 255)->unique(); $table->string('title', 140); $table->string('description', 500); $table->integer('price'); $table->unsignedInteger('category_id'); $table->unsignedInteger('brand_id'); $table->timestamps(); $table->string('created_at_ip'); $table->string('updated_at_ip'); // مفتاح خارجي على جدول التصنيفات $table->foreign('category_id') ->references('id')->on('categories') ->onDelete('cascade'); // مفتاح خارجي على جدول العلامات التجارية $table->foreign('brand_id') ->references('id')->on('brands') ->onDelete('cascade'); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists('products'); } }بذر قاعدة بيانات المشروعندرج بيانات وهمية في جداول قاعدة البيانات قصدَ الاختبار. أنشئ ملفات البذر بتنفيذ الأوامر أدناه على التوالي: php artisan make:seeder CategoriesTableSeeder php artisan make:seeder BrandsTableSeeder php artisan make:seeder ProductsTableSeederيحوي جدول المنتجات مفتاحين خارجيين لجدولي التصنيف والعلامة التجارية. لذا يجب البدء بهما (لا يصح إدراج مفتاح خارجي لتسجيلة غير موجودة في الجدول الذي مثل المفتاح الخارجي مرجعا إليه). بذر جدول التصنيفات <?php use Illuminate\Database\Seeder; class CategoriesTableSeeder extends Seeder { /** * Run the database seeds. * * @return void */ public function run() { DB::table('categories')->insert(['name' => 'MENS']); DB::table('categories')->insert(['name' => 'WOMENS']); DB::table('categories')->insert(['name' => 'KIDS']); DB::table('categories')->insert(['name' => 'FASHION']); DB::table('categories')->insert(['name' => 'CLOTHING']); } } بذر جدول العلامات التجارية<?php use Illuminate\Database\Seeder; class BrandsTableSeeder extends Seeder { /** * Run the database seeds. * * @return void */ public function run() { DB::table('brands')->insert(['name' => 'ACNE']); DB::table('brands')->insert(['name' => 'RONHILL']); DB::table('brands')->insert(['name' => 'ALBIRO']); DB::table('brands')->insert(['name' => 'ODDMOLLY']); } } بذر جدول المنتجات<?php use Illuminate\Database\Seeder; class ProductsTableSeeder extends Seeder { /** * Run the database seeds. * * @return void */ public function run() { DB::table('products')->insert(['name' => 'Mini skirt black edition', 'title' => 'Mini skirt black edition','description' => 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna','price' => 35,'category_id' => 1,'brand_id' => 1,]); DB::table('products')->insert(['name' => 'T-shirt blue edition', 'title' => 'T-shirt blue edition','description' => 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna','price' => 64,'category_id' => 2,'brand_id' => 3,]); DB::table('products')->insert(['name' => 'Sleeveless Colorblock Scuba', 'title' => 'Sleeveless Colorblock Scuba','description' => 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna','price' => 13,'category_id' => 3,'brand_id' => 2,]); } } ثم ننفذ أوامر البذر لكل جدول. خاتمةتعرفنا في هذا الدرس على تهجير قواعد البيانات وبذرها في Laravel. كما أننا حددنا هيكلة قاعدة بيانات المشروع الذي نعمل عليه. في الدروس القادمة سنتعرف على إطار عمل Eloquent الذي سنعتمد عليه للتخاطب مع قاعدة البيانات وعرض محتوياتها عند الاقتضاء. ترجمة -وبتصرّف- لمقال Laravel 5 Migrations لصاحبه Rodrick Kazembe.
  6. توفر أوبنتو خادومَيّ قواعد بيانات شهيرَين هما: قواعد بيانات MySQL.قواعد بيانات PostgreSQL.حيث تتوفران في المستودع الرئيسي (main)؛ ويشرح هذا الدرس كيفية تثبيت وضبط خادومَي قواعد البيانات آنفَيّ الذكر. MySQLإن MySQL هو خادوم قواعد بيانات سريع ومتعدد الخيوط (multi-threaded) ومتعدد المستخدمين ومرن جدًا؛ مُطوَّر للأنظمة الإنتاجية المحورية والتي تتحمل حِملًا ثقيلًا، ويمكن أيضًا تضمينه في البرمجيات سريعة النشر (mass-deployed). التثبيتنفذِّ الأمر الآتي في الطرفية لتثبيت MySQL: sudo apt-get install mysql-serverسيُطلب منك إدخال كلمة مرور للمستخدم الجذر لخادوم MySQL أثناء التثبيت. بعد أن ينتهي التثبيت، فيجب أن يبدأ خادوم MySQL تلقائيًا؛ تستطيع تنفيذ الأمر الآتي في الطرفية للتحقق إذا كان خادوم MySQL يعمل أم لا: sudo netstat -tap | grep mysqlيجب أن تشاهد شيئًا شبيهًا بما يلي بعد تنفيذ الأمر السابق: tcp 0 0 localhost:mysql *:* LISTEN 2556/mysqldإذا لم يكن يعمل الخادوم، فتستطيع تشغيله بالأمر: sudo service mysql restartالضبطتستطيع تعديل الملف ‎/etc/mysql/my.cnf لضبط الإعدادات الأساسية، مثل ملف السجل، ورقم المنفذ ...إلخ. فمثلًا لضبط MySQL ليستمع إلى الاتصالات من مضيفي الشبكة، عليك تعديل قيمة التعليمة bind-address إلى عنوان IP للخادوم: bind-address = 192.168.0.5ملاحظة: عدِّل 192.168.0.5 إلى العنوان الملائم. بعد إجراء التعديلات على ملف ‎/etc/mysql/my.cnf؛ فيجب إعادة تشغيل عفريت MySQL: sudo service mysql restartأدخل الأمر الآتي في الطرفية إذا رغبت بتغيير كلمة مرور المستخدم الجذر (root) في MySQL: sudo dpkg-reconfigure mysql-server-5.5سيُوقَف عمل عفريت MySQL، وستُسأل عن كلمة المرور الجديدة. محركات قاعدة البياناتعلى الرغم من أن الضبط الافتراضي لخادوم MySQL الموفر من حزم أوبنتو يعمل عملًا صحيحًا دون مشاكل، لكن هنالك بعض الأمور التي عليك أخذها بعين الاعتبار قبل الإكمال. صُمِّمَت قواعد بيانات MySQL للسماح بتخزين البيانات بطرقٍ مختلفة؛ يُشار لهذه الطرق إما بمحركات قواعد البيانات أو محركات التخزين (Storage engine)؛ هنالك محركان رئيسيان ستكون مهتمًا بهما: InnoDB و MyISAM؛ لا تتغير طريقة التعامل مع محركات التخزين المختلفة بالنسبة للمستخدم النهائي؛ حيث تتعامل MySQL مع الأمور بطريقة مختلفة وراء الستار، أي أنه بغض النظر عن محرك التخزين الذي تستخدمه، فإنك ستتعامل مع قواعد البيانات بنفس الطريقة تمامًا. لكل محرك إيجابياته وسلبياته؛ وبينما من الممكن دمج عدِّة محركات قواعد بيانات على مستوى الجدول، لكن ذلك خطيرٌ، فربما يقلل ذلك من الفعالية والأداء لأنك تُقسِّم الموارد بين محركين بدلًا من تخصيصها لمحرك واحد فقط. المحرك MyISAM هو الأقدم بين المحركين المذكورين؛ يمكن أن يكون أسرع من InnoDB في حالات معيّنة ويفضل الأعمال التي تتطلب القراءة فقط؛ تتمحور بعض تطبيقات الويب حول MyISAM (على الرغم أنها لن تُبطَئ إذا استخدمت InnoDB)؛ يدعم MyISAM أيضًا نوع البيانات FULLTEXT؛ الذي يسمح بالبحث بسرعة كبيرة في كمياتٍ كبيرةٍ من النص؛ لكن MyISAM قادر على قفل الجدول بأكمله فقط عند الكتابة، هذا يعني أن عمليةً واحدةً فقط تستطيع تحديث الجدول في لحظة زمنية معينّة؛ قد يكون هذا إعاقةً لتوسع تطبيق يعتمد على هذا الجدول؛ ولا يحتوي MyISAM على ميزة «journaling»، وهذا يعني أنه من الصعب استرجاع البيانات بعد حدوث انهيار.المحرك InnoDB هو محرك قواعد بيانات أكثر حداثةً، صُمِّم ليكون متوافقًا مع ACID الذي يضمن إجراء العمليات على قواعد البيانات بطريقة عملية؛ قفل الكتابة يحدث على مستوى السجل (row) ضمن الجدول؛ هذا يعني أنه من الممكن إجراء عدِّة تحديثات لسجلات جدولٍ ما في نفس الوقت؛ التخزين الموقت للبيانات يحدث في الذاكرة ضمن محرك قواعد البيانات، مما يسمح بالتخزين على أساس السجل وليس على أساس كتلة الملف (file block)؛ ولكي يتوافق مع ACID، فإن كل العمليات تحدث بطريقة «journaled» مستقلةً عن الجداول الرئيسية؛ وهذا يؤدي إلى استرجاع البيانات استرجاعًا عمليًا.إن InnoDB هو المحرك الافتراضي في MySQL 5.5 ومن المستحسن بشدة استخدامه بدلًا من MyISAM ما لم تكن تريد استخدام مزايا خاصة بذاك المحرك. الضبط المتقدم: إنشاء ملف ضبط my.cnfهنالك عدد من المعاملات التي يمكن تعديلها في ملف ضبط MySQL مما يسمح لك بتحسين أداء الخادوم مع مرور الوقت؛ ربما تجد الأداة «Percona's my.cnf generating tool» مفيدةً للإعداد الابتدائي؛ ستولد هذه الأداة ملف my.cnf ليكون أكثر ملائمةً لإمكانيات ومتطلبات خادومك. لا تستبدل ملف my.cnf المولد من Percona إذا وضعت بيانات في قاعدة بيانات، بعض التغييرات في الملف لن تسبب مشاكل لأنها تُعدِّل طريقة تخزين البيانات على القرص الصلب ولن تتمكن من تشغيل MySQL؛ إذا أردت استخدامه وكانت لديك بيانات موجودة مسبقًا، فعليك أن تجري mysqldump ثم تعيد التحميل: mysqldump --all-databases --all-routines -u root -p > ~/fulldump.sqlستُسأل عن كلمة مرور المستخدم الجذر لقواعد MySQL قبل إنشاء نسخة من البيانات؛ من المستحسن أن تتأكد أنه لا يوجد مستخدمين أو عمليات تستخدم قاعدة البيانات قبل إجراء هذه الخطوة؛ ربما تأخذ عملية النسخ بعض الوقت بناءً على مقدار البيانات الموجودة في قاعدة البيانات لديك؛ لن ترى شيئًا على الشاشة أثناء تنفيذ الأمر السابق. أغلق خادوم MySQL بعد إكمال عملية التفريغ (dump): sudo service mysql stopخذ الآن نسخةً احتياطيةً من my.cnf واستبدله بالملف الجديد: sudo cp /etc/my.cnf /etc/my.cnf.backup sudo cp /path/to/new/my.cnf /etc/my.cnfالآن احذف وأعد تهيئة مجال قواعد البيانات وتأكد أن الملكية صحيحة قبل إعادة تشغيلMySQL: sudo rm -rf /var/lib/mysql/* sudo mysql_install_db sudo chown -R mysql: /var/lib/mysql sudo service start mysqlكل ما تبقى الآن هو إعادة استيراد بياناتك؛ وللحصول على فكرة عن مدى إتمام عملية الاستيراد، فربما تجد الأداة pv‏ (Pipe Viewer) مفيدةً؛ الأمر الآتي يظهر كيفية تثبيت واستخدام pv لهذه الحالة، ربما لا تريد أن تستخدمها وكل ما عليك فعله هو استبدال pv بالأمر cat؛ تجاهل أية أوقات متوقعة للانتهاء (ETA) مولدة من pv؛ لأنها مبنية على الوقت المستغرق لكي يُعالَج كل سجل من الملف، لكن سرعة إدراج البيانات قد تختلف اختلافًا كبيرًا من سجل إلى سجل: sudo apt-get install pv pv ~/fulldump.sql | mysqlملاحظة: هذا ليس ضروريًا لكل تعديلات my.cnf؛ أغلبية المتغيرات التي قد ترغب في تعديلها لتحسين الأداء يمكن أن تُغيَّر حتى وإن كان يعمل الخادوم؛ تأكد من الحصول على نسخة احتياطية من ملفات الضبط والبيانات قبل إجراء التعديلات. MySQL Tunerالأداة «MySQL Tuner» هي أداة مفيدة تستطيع الاتصال إلى خدمة MySQL التي تعمل وتوفر اقتراحات عن كيفية ضبطها بأفضل ضبط لحالتك؛ وكما كان يعمل الخادوم لوقتٍ أطول، كلما كانت «النصيحة» التي سيوفرها mysqltuner أفضل؛ خذ بعين الاعتبار الانتظار لمدة 24 ساعة في بيئة إنتاجية قبل تشغيل هذه الأداة؛ تستطيع تثبيت mysqltuner من مستودعات أوبنتو: sudo apt-get install mysqltunerثم تشغيلها بعد تثبيتها بالأمر: mysqltunerوانتظر التقرير النهائي، سيوفر القسم العلوي معلوماتٍ عن خادوم قاعدة البيانات، ويوفر القسم السفلي اقتراحاتٍ لكي تعدلها في ملف my.cnf؛ يمكن تعديل أغلبية الاقتراحات على الخادوم مباشرةً دون إعادة تشغيله، انظر إلى توثيق MySQL الرسمي للمتغيرات المناسبة لتعديلها في البيئات الإنتاجية؛ ما يلي هو جزء من تقرير من قاعدة بيانات إنتاجية الذي يُظهِر أن هنالك بعض الفائدة من زيادة مقدار ذاكرة تخزين الطلبية: -------- Recommendations ----------------------------------------------------- General recommendations: Run OPTIMIZE TABLE to defragment tables for better performance Increase table_cache gradually to avoid file descriptor limits Variables to adjust: key_buffer_size (> 1.4G) query_cache_size (> 32M) table_cache (> 64) innodb_buffer_pool_size (>= 22G)تعليق أخير عن ضبط قواعد البيانات: بينما نستطيع أن نقول أن بعض الإعدادات هي الأفضل، لكن قد يختلف الأداء من تطبيق لآخر؛ على سبيل المثال، ما يعمل عملًا ممتازًا لووردبريس (Wordpress) قد لا يكون الأفضل لدروبال (Drupal) أو جوملا (Joomla) أو التطبيقات التجارية؛ الأداء متعلقٌ بأنواع الطلبيات واستخدام الفهارس، وإذا ما كان تصميم قاعدة البيانات جيدًا، وهكذا... ربما من الجيد إنفاق بعض الوقت في البحث عن إعدادات ملائمة لقواعد البيانات بناءً على التطبيقات التي تستخدمها؛ لكن بعد أن تتجاوز التعديلات حدًا معيّنًا، فإن أيّة تغييرات تجريها لا تتسبب إلا بتحسين بسيط جدًا في أداء التطبيق، ومن الأفضل لك تحسين التطبيق نفسه، أو التفكير في توسيع خادوم MySQL إما باستخدام عتاد أفضل أو بإضافة خواديم تابعة (slave). مصادرراجع الموقع الرئيسي لقواعد MySQL لمزيدٍ من المعلومات.التوثيق الكامل متوفر بصيغ online و offline من «MySQL Developers portal».لمعلومات عامة حول SQL، انظر إلى كتاب «Using SQL Special Edition».صفحة ويكي أوبنتو «Apache MySQL PHP» فيها بعض المعلومات المفيدة.PostgreSQLPostgreSQL هي قاعدة بيانات علائقية تعتمد على الكائنات وتملك ميزات أنظمة قواعد البيانات التجارية التقليدية مع تحسينات موجودة في الجيل الجديد من أنظمة DBMS. التثبيتأدخل الأمر الآتي في الطرفية لتثبيت PostgreSQL: sudo apt-get install postgresqlبعد انتهاء التثبيت، عليك ضبط خادوم PostgreSQL بناءً على متطلباتك، على الرغم من أن الضبط الافتراضي قابل للاستخدام. الضبطالاتصال عبر TCP/IP معطَّل افتراضيًا؛ تدعم PostgreSQL عدّة طرق للاستيثاق من العميل؛ طريقة الاستيثاق IDENT تُستعمَل للمستخدمين المحليين ولمستخدم postgres ما لم يُضبَط غير ذلك؛ رجاءً راجع «PostgreSQL Administrator's Guide» إذا أردت ضبط بدائل مثل Kerberos. سنفترض في ما يلي أنك ستُفعِّل اتصالات TCP/IP وتستخدم طريقة MD5 للاستيثاق من العميل؛ تُخزَّن ملفات ضبط PostgreSQL في المجلد ‎/etc/postgresql/<version>/main؛ على سبيل المثال، إذا ثبتت خادوم PostgreSQL 9.1، فإن ملفات الضبط ستُخزَّن في المجلد ‎/etc/postgresql/9.1/main. تنويه: لضبط الاستيثاق بطريقة ident، فأضف مدخلات إلى ‎/etc/postgresql/9.1/‎ main/pg_ident.conf؛ هنالك تعليقات تفصيلية في الملف لتساعدك. لتفعيل اتصالات TCP/IP، عليك تعديل الملف ‎/etc/postgresql/9.1/main/postgresql.conf ومن ثم تحديد السطر: ‎‎#listen_addresses = 'localhost‎‎'‎ ثم تغييره إلى: listen_addresses = '*'ملاحظة: للسماح باتصالات IPv4 و IPv6، استبدل «localhost» بالرمز «::». ربما تريد تعديل بقية المعاملات، إذا كنت تعرف ماذا تفعل! للتفاصيل، ارجع إلى ملف الضبط أو إلى توثيق PostgreSQL. الآن وبعد أن استطعنا الاتصال بخادوم PostgreSQL فإن الخطوة الآتية هي ضبط كلمة مرور للمستخدم postgres؛ نفذ الأمر الآتي في الطرفية للاتصال بقاعدة بيانات PostgreSQL الافتراضية: sudo -u postgres psql template1يتصل الأمر السابق بقاعدة بيانات PostgreSQL المسماة template1 كالمستخدم postgres؛ بعد أن تتصل إلى خادوم PostgreSQL وتحصل على مِحَث لإدخال تعليمات SQL، فيمكنك إدخال أمر SQL الآتي في مِحَث psql لضبط كلمة المرور للمستخدم postgres: ALTER USER postgres with encrypted password 'your_password';بعد ضبط كلمة المرور، عدِّل الملف ‎/etc/postgresql/9.1/main/pg_hba.conf لاستخدام استيثاق MD5 مع المستخدم postgres: local all postgres md5في النهاية، يجب أن تُعيد تشغيل خدمة PostgreSQL لتهيئة الضبط الجديد، وذلك بإدخال الأمر الآتي من الطرفية: sudo service postgresql restartتحذير: الضبط السابق ليس كاملًا بأي شكل من الأشكال، رجاءً راجع «PostgreSQL Administrator's Guide» لمعاملات ضبط إضافية. يمكنك اختبار اتصالات الخادوم من الأجهزة الأخرى باستخدام عملاء PostgreSQL: sudo apt-get install postgresql-client psql -h postgres.example.com -U postgres -Wملاحظة: استبدل اسم النطاق في المثال السابق باسم نطاقك الفعلي. مصادركما ذُكِر سابقًا، فإن «PostgreSQL Administrator's Guide» هو مصدر رائع، وهو متوفر أيضًا في حزمة postgresql-doc-9.1؛ نفذ ما يلي لتثبيت تلك الحزمة:sudo apt-get install postgresql-doc-9.1أدخِل الوصلة file:///usr/share/doc/postgresql-doc-9.1/html/index.html في شريط العنوان في متصفحك لمشاهدة الدليل.راجع أيضًا صفحة ويكي أوبنتو «PostgreSQL» لمزيدٍ من المعلومات.ترجمة -وبتصرف- للمقال Ubuntu Server Guide: Databases.
  7. هناك العديد من لغات قواعد البيانات SQL التي تعمل على أنظمة اللينكس واليونكس، ومن أشهر لغات قواعد البيانات العلائقية التي تعمل في بيئات الخوادم هما MySQL وMariaDB. ومع ذلك، مثل أغلب البرامج، هذه الأدوات يمكن أن تكون الاحتياجات الأمنية إذا تم تكوينها بشكل غير صحيح، هذا الشرح التعليمي سوف يرشدك لبعض الخطوات الأساسية التي يمكن اتخاذها لتأمين قاعدة البيانات الخاصة بك سواء MariaDB أو MySQL، والتأكد من أنها ليست بابًا مفتوحًا إلى VPS الخاص بك. من أجل البساطة والوضوح، سوف نستخدم MySQL على خادوم Ubuntu كمثال، ومع أن هذه التقنيات يمكن تطبيقها على توزيعات لينكس الأخرى، ويمكن استخدامها مع MariaDB كذلك. الإعداد الأوليMySQL يمنحك فرصة لاتخاذ الخطوة الأولى نحو تحقيق الأمن أثناء التثبيت، وسوف نطلب منكم وضع كلمة سر root (الجذر). $ sudo apt-get install mysql-server Configuring mysql-server-5.5 While not mandatory, it is highly recommended that you set a password for the MySQL administrative "root" user. If this field is left blank, the password will not be changed. New password for the MySQL "root" user:يمكنك دائما تعيين كلمة سر root في وقت لاحق، ولكن ليس هناك سبب لتخطي هذه الخطوة، لذلك يجب تأمين حساب المسؤول الخاص بك من البداية. بمجرد اكتمال التثبيت، يجب علينا تشغيل عدد قليل من النصوص المدرجة. أولاً، سوف نستخدم "mysql_install_db" وهو سكريبت نصي لإنشاء تصميم قواعد البيانات الخاصة بنا. $ sudo mysql_install_dbبعد ذلك، قم بتشغيل السكريبت الذي يسمى "mysql_secure_installation"، وسيرشدنا لبعض الإجراءات التي من شأنها إزالة بعض الافتراضات التي تشكل خطرا على استخدامها في بيئة الإنتاج. $ sudo mysql_secure_installationأولاً سوف يطلب منك إدخال كلمة السر الجذر وستقوم بإدخالها أثناء التثبيت، وبعد ذلك مباشرة ، سوف يطلب منك سلسلة من الأسئلة، بدءا من إذا كنت ترغب في تغيير كلمة سر الجذر. هذه هي فرصة أخرى لتغيير كلمة المرور الخاصة بك إلى أي شيء آمن إذا لم تكن قد فعلت ذلك بالفعل. يجب أن تكون الإجابة "Y" (نعم) لجميع الأسئلة المتبقية. سيؤدي ذلك إلى إزالة قدرة أي شخص لتسجيل الدخول إلى MySQL افتراضيا، وتعطيل تسجيل الدخول عن بعد على حساب المسؤول، وإزالة بعض قواعد بيانات الاختبار غير الآمنة، وتحديث قاعدة البيانات التي تعمل حاليا لاعتماد هذه التغيرات. اعتبارات أمنيةالقاعدة البسيطة لزيادة حماية MySQL (ومعظم الأنظمة الأخرى) هو إعطاء صلاحيات النفاذ فقط عند الضرورة. أحيانا لكي تكون بياناتك آمنة يجب أن توزان بين الراحة والأمان. في هذا الدليل، سوف نميل إلى الجانب الأمني، لذا فإن استخدامك الخاص لقاعدة البيانات يمكن أن يدفعك لإنتقاء أحد هذه الخيارات. زيادة الأمن من خلال ملف My.cnfملف الإعدادت الرئيسية في MySQL هو ملف يسمى "my.cnf" الموجود في "/etc/mysql/" هذا الامتداد على أوبونتو وامتداد "/etc/" على بعض الخواديم الأخرى. سوف نقوم بتغيير بعض الإعدادات في هذا الملف لتأمين MySQL الخاصة بنا. فتح الملف مع صلاحيات الجذر، تغيير مسار الامتداد حسب الحاجة إذا كنت تتبع هذا الشرح التعليمي على نظام مختلف: $ sudo nano /etc/mysql/my.cnfالإعداد الأولي التي يجب علينا أن نتحقق منه "وضع عنوان IP" ضمن قسم "[mysqld]". ويجب تعيين هذا الإعداد على جهاز الشبكة المحلي loopback ، وهو "127.0.0.1". $ bind-address = 127.0.0.1هذا يجعل من أن MySQL لا تقبل الاتصالات من أي مكان باستثناء الجهاز المحلي. إذا كنت بحاجة للوصول إلى قاعدة البيانات من جهاز آخر، خذ بالاعتبار الاتصال عن طريق SSH للقيام بالاستعلام وادارة قاعدة البيانات الخاصة بك محليا وإرسال النتائج من خلال قناة SSH. الفجوة التالية التي سوف نعدلها، هي وظيفة تتيح لك الوصول إلى نظام الملفات من داخل MySQL، يمكن أن يكون لها تداعيات أمنية خطيرة ويجب ايقافها إلا إذا كنت في حاجة شديدة لها. في نفس المقطع من الملف، سوف نقوم بإضافة التوجيه لتعطيل هذه القدرة على تحميل الملفات المحلية: local-infile=0إذا كان لدينا مساحة كافية ولا تعمل على قاعدة بيانات ضخمة، فإنه يمكن أن يكون مفيدا لتسجيل معلومات إضافية لمراقبة أي نشاط مثير للشبهة. تسجيل معلومات أكثر من اللازم يضعف الأداء، لذلك قم بوزن أي شيء تحتاجه بعناية. يمكنك وضع تسجيل الأحداث المتغيرة داخل القسم نفسه "[mysqld]" التي قمنا بالإضافة فيها: log=/var/log/mysql-logfileتأكد من أن سجل MySQL يعمل، سجل الأخطاء، وسجل MySQL ليس سهل القراءة: $ sudo ls -l /var/log/mysql* -rw-r----- 1 mysql adm 0 Jul 23 18:06 /var/log/mysql.err -rw-r----- 1 mysql adm 0 Jul 23 18:06 /var/log/mysql.log /var/log/mysql: total 28 -rw-rw---- 1 mysql adm 20694 Jul 23 19:17 error.logتأمين MySQL من الداخلهناك عدد من الخطوات التي يمكنك اتخاذها أثناء استخدام MySQL لتحسين الوضع الأمني. سوف نقوم بإدخال الأوامر في هذا القسم في بداخل واجهة MySQL ، لذلك نحن بحاجة إلى تسجيل الدخول. $ mysql -u root -pسيطلب منك إدخال كلمة سر الجذر التي قمت بإعدادها في وقت سابق. تأمين كلمات السر والمستخدمين المرتبطينأولاً، تأكد من وجود مستخدمين بدون كلمة مرور أو المضيف المرتبط في MySQL: SELECT User,Host,Password FROM mysql.user; +------------------+-----------+-------------------------------------------+ | user | host | password | +------------------+-----------+-------------------------------------------+ | root | localhost | *DE06E242B88EFB1FE4B5083587C260BACB2A6158 | | demo-user | % | | | root | 127.0.0.1 | *DE06E242B88EFB1FE4B5083587C260BACB2A6158 | | root | ::1 | *DE06E242B88EFB1FE4B5083587C260BACB2A6158 | | debian-sys-maint | localhost | *ECE81E38F064E50419F3074004A8352B6A683390 | +------------------+-----------+-------------------------------------------+ 5 rows in set (0.00 sec)كما ترون في مثالنا هذا "المستخدم التجريبي " ليس لديه كلمة مرور، وهو ساري المفعول بغض النظر عن ما هو عليه في المضيف، ويعتبر هذا آمن جدا. يمكننا وضع كلمة سر للمستخدم مع هذا الأمر Change "كلمة المرور الجديدة" أدخل كلمة المرور التي ترغب بها. UPDATE mysql.user SET Password=PASSWORD('newPassWord') WHERE User=""demo-user";إذاً علينا التحقق من جدول المستخدم مرة أخرى، وسوف نرى أن المستخدم التجريبي لديه الآن كلمة سر: SELECT User,Host,Password FROM mysql.user;+------------------+-----------+-------------------------------------------+ | user | host | password | +------------------+-----------+-------------------------------------------+ | root | localhost | *DE06E242B88EFB1FE4B5083587C260BACB2A6158 | | demo-user | % | *D8DECEC305209EEFEC43008E1D420E1AA06B19E0 | | root | 127.0.0.1 | *DE06E242B88EFB1FE4B5083587C260BACB2A6158 | | root | ::1 | *DE06E242B88EFB1FE4B5083587C260BACB2A6158 | | debian-sys-maint | localhost | *ECE81E38F064E50419F3074004A8352B6A683390 | +------------------+-----------+-------------------------------------------+ 5 rows in set (0.00 sec)إذا ما نظرت هذا الحقل"host"، سترى أن لا يزال لدينا "٪"، هي عبارة عن بطاقة بديلة وهذا يعني أي مضيف. وليس هذا ما نريده، دعونا نغيرها إلى " localhost". UPDATE mysql.user SET Host='localhost' WHERE User="demo-user";إذا تحققنا مرة أخرى، يمكننا أن نرى أن جدول المستخدم لديه الآن الحقول المناسبة. SELECT User,Host,Password FROM mysql.user;إذا كان لدينا جدول يحتوي على مستخدمين فارغين (لا يجب في هذه المرحلة أن يكونوا "mysql_secure_installation", سنغطي هذه الناحية بأي حال من الأحوال لاحقا)، وينبغي علينا إزالتهم. للقيام بذلك، يمكننا استخدام الأمور التالي لحذف المستخدمين الفارغين من جدول الوصول: DELETE FROM mysql.user WHERE User="";بعد أن يتم تعديل جدول المستخدم، نحن بحاجة إلى إدخال الأمر التالي لتنفيذ صلاحيات جديدة: FLUSH PRIVILEGES;إنشاء مستخدمين محددين لتطبيقات معينة طريقة تشغيل العمليات داخل لينكس تكون معزولة لكل مستخدم على حدى، وتستخدم قاعدة بيانات MySQL نفس طريقة العزل. كل تطبيق يستخدم MySQL يجب أن يمتلك مستخدم خاص به ولديه صلاحيات محدودة ويستطيع الوصول إلى قواعد البيانات التي يحتاج لتشغيلها فقط. عندما نقوم بإعداد تطبيق جديد لاستخدام MySQL، يجب أن ننشئ قواعد البيانات التي يحتاجها هذا التطبيق: create database testDB; Query OK, 1 row affected (0.00 sec)بعد ذلك، يجب علينا إنشاء مستخدم لإدارة قاعدة البيانات، ومنحه الصلاحيات التي يحتاجها فقط، وهذه تختلف من تطبيق لآخر، وبعض الاستخدامات تحتاج لصلاحيات مفتوحة أكثر من غيرها. لإنشاء مستخدم جديد، استخدم الأمر التالي: CREATE USER 'demo-user'@'localhost' IDENTIFIED BY 'password';يمكننا منح المستخدم الجديد صلاحيات على الجدول الجديد بالأمر التالي. انظر الشرح التعليمي حول كيفية إنشاء مستخدم ومنح صلاحيات جديدة في MySQL لمعرفة المزيد عن الصلاحيات المحددة: GRANT SELECT,UPDATE,DELETE ON testDB.* TO 'demo-user'@'localhost';وكمثال على ذلك، إذا كنا بحاجة إلى وقت لاحق لإلغاء الصلاحيات من الحساب، يمكن أن نستخدم الأمر التالي: REVOKE UPDATE ON testDB.* FROM 'demo-user'@'localhost';إذا كنا بحاجة إلى كافة الصلاحيات على قاعدة بيانات معينة، يمكننا تحديد ذلك بما يلي: GRANT ALL ON testDB.* TO 'demo-user'@'localhost';لإظهار الصلاحيات الحالية للمستخدم، علينا أولا أن ننفذ الصلاحيات حددناه باستخدام أمر "flush privileges"، ثم بعد ذلك يمكننا الاستعلام عن الصلاحيات التي بحوزة المستخدم. FLUSH PRIVILEGES; show grants for 'demo-user'@'localhost'; Grants for demo-user@localhost GRANT USAGE ON *.* TO 'demo-user'@'localhost' IDENTIFIED BY PASSWORD '*2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19' GRANT SELECT, UPDATE, DELETE ON `testDB`.* TO 'demo-user'@'localhost' 2 rows in set (0.00 sec)دائما امسح الصلاحيات عندما تنتهي من إجراء التغييرات. تغيير المستخدم الجذرخطوة إضافية واحدة وهي، ربما تريد تغيير اسم الجذر(root login name )، فإذا كان الهاكر يحاول أن يقوم بتسجيل الدخول باسم الروت في MySQL ، فسوف يحتاج إلى تنفيذ خطوة إضافية هي العثور على اسم المستخدم. تستطيع تغيير اسم المستخدم روت باستخدام الأمر التالي: rename user 'root'@'localhost' to 'newAdminUser'@'localhost';يمكننا أن نرى التغيير باستخدام نفس الاستعلام الذي استخدمناه لقاعدة بيانات المستخدم: select user,host,password from mysql.user;مرة أخرى، يجب علينا مسح الصلاحيات التغيرات التي حدثت: FLUSH PRIVILEGES;تذكر أنه سوف تسجل دخول إلى MySQL مثل اسم مستخدم تم إنشاؤه حديثا عندما ترغب في أداء المهام الإدارية: mysql -u newAdminUser -pبأي حال من الأحوال هذه قائمة شاملة من الاجراءات الأمنية لقواعد البيانات MySQL, MariaDB، وقد أصبح لديك مقدمة جيدة لأنواع القرارات التي ستتخذها عندما تريد تأمين قواعد البيانات الخاصة بك. يمكن الاطلاع على مزيد من المعلومات حول الإعدادت والأمن في قواعد بيانات المواقع MySQL وMariaDB إضافة الى صفحات المختصين، ويمكن للتطبيقات التي اخترت استخدامها أن تقدم المشورة الأمنية. ترجمة -وبتصرّف- للمقال: How To Secure MySQL and MariaDB Databases in a Linux VPS.