<?xml version="1.0"?>
<rss version="2.0"><channel><title>DevOps: MySQL</title><link>https://academy.hsoub.com/devops/servers/databases/mysql/?d=4</link><description>DevOps: MySQL</description><language>ar</language><item><title>&#x643;&#x64A;&#x641;&#x64A;&#x629; &#x62A;&#x62B;&#x628;&#x64A;&#x62A; MySQL &#x639;&#x644;&#x649; &#x623;&#x648;&#x628;&#x648;&#x646;&#x62A;&#x648; 18.04</title><link>https://academy.hsoub.com/devops/servers/databases/mysql/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%AA%D8%AB%D8%A8%D9%8A%D8%AA-mysql-%D8%B9%D9%84%D9%89-%D8%A3%D9%88%D8%A8%D9%88%D9%86%D8%AA%D9%88-1804-r433/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2019_08/5d46acbf6e16e_MySQL.jpg.ad219e4ba960a98da7bb47a4c55ce1ea.jpg" /></p>

<p>
	MySQL هو نظام مفتوح المصدر لإدارة قواعد البيانات، ويُثبت غالبا كجزء من <a href="https://academy.hsoub.com/devops/servers/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%AA%D8%AB%D8%A8%D9%8A%D8%AA-%D9%88%D8%A5%D8%B9%D8%AF%D8%A7%D8%AF-%D8%AA%D8%B7%D8%A8%D9%8A%D9%82%D8%A7%D8%AA-lamp-%D8%B9%D9%84%D9%89-%D8%A3%D9%88%D8%A8%D9%86%D8%AA%D9%88-r195/" rel="">الحزمة الشهيرة LAMP (Linux, Apache, MySQL, PHP/Python/Perl)</a>. يستخدم MySQL قواعد بيانات علائقية و SQL (لغة استعلام مهيكلة) لإدارة بياناته.
</p>

<p>
	الطريقة المختصرة لتثبيت MySQL سهلة جدا: حدث الحزمة الرئيسية، ثم ثبت حزمة mysql-server ثم شغِّل سكريبت الحماية المضمن.
</p>

<pre class="ipsCode">
<span class="hljs-variable">$ </span>sudo apt update
<span class="hljs-variable">$ </span>sudo apt install mysql-server
<span class="hljs-variable">$ </span>sudo mysql_secure_installation
</pre>

<h2 id="-">
	متطلبات أولية
</h2>

<p>
	لإكمال هذا الإعداد، ستحتاج إلى: خادم أوبونتو 18.04 مُعد كما في <a href="https://academy.hsoub.com/devops/linux/%D8%A7%D9%84%D8%AA%D9%87%D9%8A%D8%A6%D8%A9-%D8%A7%D9%84%D8%A3%D9%88%D9%84%D9%8A%D8%A9-%D9%84%D8%AE%D8%A7%D8%AF%D9%85-%D8%A3%D9%88%D8%A8%D9%88%D9%86%D8%AA%D9%88-1804-r431/" rel="">مقال الإعداد الأولي لِخادم أوبونتو</a>. متضمنا مستخدم غير مسؤول (non-root user) بصلاحيات <code>sudo</code> وجدار حماية.
</p>

<p>
	<a class="ipsAttachLink ipsAttachLink_image" href="https://academy.hsoub.com/uploads/monthly_2019_08/5d46acb284bde_MySQL.jpg.aa705a9f0e3907438d6c0591f4fa07c4.jpg" data-fileid="30945" rel=""><img class="ipsImage ipsImage_thumbnailed" data-fileid="30945" data-unique="mtg6gblpk" src="https://academy.hsoub.com/uploads/monthly_2019_08/5d46acb29db8f_MySQL.thumb.jpg.d4a557de17270e582ca566c841fab5d6.jpg" alt="كيفية تثبيت MySQL.jpg"></a>
</p>

<h2 id="-1-mysql">
	خطوة 1 - تثبيت MySQL
</h2>

<p>
	تتضمن تلقائيا حزمة مخزن APT في أوبونتو 18.04 أحدث إصدار فقط من MySQL. في الوقت الراهن، أحدث اصدار هو MySQL 5.7.
</p>

<p>
	للتثبيت، حدّث الحزمة الرئيسية على الخادم باستخدام الأمر <code>apt</code>:
</p>

<pre class="ipsCode">
<span class="hljs-variable">$ </span>sudo apt update
</pre>

<p>
	ثم ثبت الحزمة الافتراضية:
</p>

<pre class="ipsCode">
$ sudo apt <span class="hljs-keyword">install</span> mysql-<span class="hljs-keyword">server</span>
</pre>

<p>
	سيُثبت هذا الأمر MySQL لكنه لن يتيح لك إعداد كلمة مرور أو القيام بأي تعديل على الإعدادات. مما يجعل تثبيت MySQL غير آمن وسيتم شرح ذلك لاحقا.
</p>

<h2 id="-2-mysql">
	خطوة 2 - إعداد MySQL
</h2>

<p>
	ستحتاج لِتشغيل سكريبت الحماية المضمن للحصول على تثبيت صحيح. الأمر الذي سيغير بعض الخيارات الأقل أمنا مثل دخول المستخدمين المسؤولين عن بعد أو عينات المستخدمين. كنا نقوم بإعداد هذه البيانات يدويا في إصدارات سابقة، لكن في هذا الإصدار يتم إعدادها تلقائيا.
</p>

<p>
	قم بتشغيل السكربت:
</p>

<pre class="ipsCode">
<span class="hljs-variable">$ </span>sudo mysql_secure_installation
</pre>

<p>
	ستنتقل عبر بعض الخيارات حيث يمكنك القيام ببعض التغييرات على إعدادات حماية MySQL المٌعدة أثناء التثبيت. الخيار الأول سيسألك إن كنت تريد إعداد إضافة التحقق بكلمة المرور والمستخدمة لقياس قوة كلمة مرور MySQL. بغض النظر عن خيارك، الخيار التالي سيكون لإعداد كلمة مرور للمستخدم المسؤول ل MySQL. أدخل وأكِد كلمة مرور آمنة.
</p>

<p>
	بعد ذلك يمكنك الضغط على <code>Y</code> ثم <code>ENTER</code> لقبول الإعداد الافتراضي لبقية الأسئلة التالية. سيقوم ذلك بحذف بعض المستخدمين المجهولين وقاعدة البيانات التجريبية، وإلغاء تفعيل دخول المستخدمين المسؤولين عن بعد، وسيُحمل الإعدادات الجديدة التي قمت بعملها على MySQL.
</p>

<p>
	لإعداد دليل بيانات MySQL يمكنك استخدام <code>mysql_install_db</code> للإصدارات قبل 5.7.6 و <code>mysqld --initialize</code> لتهيئة الإصدار 5.7.6 والإصدارات الأحدث. لكن إن كنت قد ثبتت MySQL من موزع Debian كما في الخطوة 1، فإن دليل البيانات قد تم إعداده تلقائيا ولن تحتاج للقيام بأي شيء. وبحال أو بآخر إن قمت بتنفيذ الأمر، فسترى الخطأ التالي:
</p>

<p>
	<strong>المخرجات:</strong>
</p>

<pre class="ipsCode">
<span class="hljs-symbol">mysqld:</span> Can<span class="hljs-string">'t create directory '</span>/var/<span class="hljs-class"><span class="hljs-keyword">lib</span>/<span class="hljs-title">mysql</span>/' (<span class="hljs-title">Errcode</span>: 17 - <span class="hljs-title">File</span> <span class="hljs-title">exists</span>)</span>

. . .

<span class="hljs-number">2018</span>-<span class="hljs-number">04</span>-<span class="hljs-number">23</span><span class="hljs-symbol">T13:</span><span class="hljs-number">48</span>:<span class="hljs-number">00.572066</span>Z <span class="hljs-number">0</span> [ERROR] Aborting
</pre>

<p>
	لاحظ أنه حتى إن قمت بإعداد كلمة مرور لمستخدم MySQL المسؤول، فإن هذا المستخدم ليس معدًا للتحقق عبر كلمة المرور عند الاتصال بشاشة اوامر MySQL. إن أردت تغيير هذا الإعداد اتبع الخطوة 3.
</p>

<h2 id="-3-">
	خطوة 3 - (اختيارية) إعداد مصادقة وصلاحيات المستخدم
</h2>

<p>
	المستخدم المسؤول في أنظمة أوبونتو التي تستخدم MySQL 5.7 مُعد للمصادقة تلقائيا باستخدام اضافة <code>auth_socket</code> بدلا من كلمة المرور. توفر هذه الإضافة أمانًا أكبر وسهولةً في الاستخدام في حالات متعددة، لكنها تضيف بعض التعقيد عند حاجتك للسماح لبرنامج خارجي بالوصول للمستخدم (مثل phpMyAdmin).
</p>

<p>
	حتى تتمكن من الدخول إلى MySQL كمستخدم رئيسي باستخدام كلمة مرور، تحتاج لتبديل طريقة المصادقة من <code>auth_socket</code> إلى <code>mysql_native_password</code>. للقيام بذلك افتح شاشة اوامر MySQL:
</p>

<pre class="ipsCode">
 <span class="hljs-variable">$ </span>sudo mysql
</pre>

<p>
	ثم تأكد من طريقة المصادقة لكل حساب مستخدم MySQL باستخدام الأمر التالي:
</p>

<pre class="ipsCode">
mysql&gt; SELECT <span class="hljs-keyword">user</span>,authentication_string,plugin,host <span class="hljs-keyword">FROM</span> mysql.<span class="hljs-keyword">user</span>;
</pre>

<p>
	المخرجات:
</p>

<pre class="ipsCode">
+------------------+-------------------------------------------+-----------------------+-----------+

|<span class="hljs-string"> user             </span>|<span class="hljs-string"> authentication_string                     </span>|<span class="hljs-string"> plugin                </span>|<span class="hljs-string"> host      </span>|

+------------------+-------------------------------------------+-----------------------+-----------+

|<span class="hljs-string"> root             </span>|<span class="hljs-string">                                           </span>|<span class="hljs-string"> auth_socket           </span>|<span class="hljs-string"> localhost </span>|

|<span class="hljs-string"> mysql.session    </span>|<span class="hljs-string"> *THISISNOTAVALIDPASSWORDTHATCANBEUSEDHERE </span>|<span class="hljs-string"> mysql_native_password </span>|<span class="hljs-string"> localhost </span>|

|<span class="hljs-string"> mysql.sys        </span>|<span class="hljs-string"> *THISISNOTAVALIDPASSWORDTHATCANBEUSEDHERE </span>|<span class="hljs-string"> mysql_native_password </span>|<span class="hljs-string"> localhost </span>|

|<span class="hljs-string"> debian-sys-maint </span>|<span class="hljs-string"> *CC744277A401A7D25BE1CA89AFF17BF607F876FF </span>|<span class="hljs-string"> mysql_native_password </span>|<span class="hljs-string"> localhost </span>|

+------------------+-------------------------------------------+-----------------------+-----------+

4 rows in set (0.00 sec)
</pre>

<p>
	يمكنك ملاحظة أن المستخدم المسؤول في هذا المثال يستخدم المصادقة بواسطة إضافة <code>auth_socket</code>. لإعداد حساب المستخدم المسؤول ليستخدم المصادقة بكلمة المرور استخدم أمر <code>ALTER USER</code> التالي. تأكد من تغيير <span style="color:red;"><code>password</code></span> إلى كلمة مرور قوية من اختيارك وتذكر أن هذا الأمر سيغير كلمة المرور التي وضعتها في خطوة 2:
</p>

<pre class="ipsCode">
mysql&gt; ALTER USER <span class="hljs-string">'root'</span>@<span class="hljs-string">'localhost'</span> IDENTIFIED <span class="hljs-keyword">WITH</span> mysql_native_password <span class="hljs-keyword">BY</span> <span class="hljs-string">'password'</span>;
</pre>

<p>
	ثم نفذ الأمر <code>FLUSH PRIVILEGES</code> الذي يوجه الخادم بإعادة تحميل جداول الصلاحيات كي تعمل التغييرات التي قمت بها:
</p>

<pre class="ipsCode">
mysql&gt; FLUSH PRIVILEGES<span class="hljs-comment">;</span>
</pre>

<p>
	تحقق من طريقة المصادقة لكل حساب مستخدم مجددا للتأكد من أن المستخدم المسؤول لم يعد يستخدم المصادقة باستخدام إضافة <code>auth_socket</code>:
</p>

<pre class="ipsCode">
mysql&gt; SELECT <span class="hljs-keyword">user</span>,authentication_string,plugin,host <span class="hljs-keyword">FROM</span> mysql.<span class="hljs-keyword">user</span>;
</pre>

<p>
	المخرجات:
</p>

<pre class="ipsCode">
+------------------+-------------------------------------------+-----------------------+-----------+

|<span class="hljs-string"> user </span>|<span class="hljs-string"> authentication_string </span>|<span class="hljs-string"> plugin</span>|<span class="hljs-string"> host  </span>|

+------------------+-------------------------------------------+-----------------------+-----------+

|<span class="hljs-string"> root </span>|<span class="hljs-string"> *3636DACC8616D997782ADD0839F92C1571D6D78F </span>|<span class="hljs-string"> mysql_native_password </span>|<span class="hljs-string"> localhost </span>|

|<span class="hljs-string"> mysql.session</span>|<span class="hljs-string"> *THISISNOTAVALIDPASSWORDTHATCANBEUSEDHERE </span>|<span class="hljs-string"> mysql_native_password </span>|<span class="hljs-string"> localhost </span>|

|<span class="hljs-string"> mysql.sys</span>|<span class="hljs-string"> *THISISNOTAVALIDPASSWORDTHATCANBEUSEDHERE </span>|<span class="hljs-string"> mysql_native_password </span>|<span class="hljs-string"> localhost </span>|

|<span class="hljs-string"> debian-sys-maint </span>|<span class="hljs-string"> *CC744277A401A7D25BE1CA89AFF17BF607F876FF </span>|<span class="hljs-string"> mysql_native_password </span>|<span class="hljs-string"> localhost </span>|

+------------------+-------------------------------------------+-----------------------+-----------+

4 rows in set (0.00 sec)
</pre>

<p>
	يمكنك رؤية أن المستخدم المسؤول أصبح يستخدم المصادقة بكلمة المرور في هذا المثال. بعد أن تتأكد من ذلك يمكنك الخروج من شاشة اوامر MySQL:
</p>

<pre class="ipsCode">
mysql&gt; <span class="hljs-keyword">exit</span>
</pre>

<p>
	بدلا من ذلك؛ قد يفضل البعض استخدام مستخدم خصص للاتصال ب MySQL. لِإنشاء مستخدم مخصص افتح شاشة اوامر MySQL مجددا:
</p>

<pre class="ipsCode">
 <span class="hljs-variable">$ </span>sudo mysql
</pre>

<p>
	<strong>ملاحظة:</strong> إن كنت تستخدم المصادقة بكلمة المرور للمستخدم المسؤول كما تم الشرح سابقا؛ فستحتاج لاستخدام أمر آخر للدخول إلى شاشة اوامر MySQL. سيقوم الأمر التالي بتشغيل عميل MySQL مع صلاحيات مستخدم عادي. وستحصل على صلاحيات المسؤول فقط عن طريق المصادقة:
</p>

<pre class="ipsCode">
 <span class="hljs-variable">$ </span>mysql -u root -p
</pre>

<p>
	بعد ذلك قم بإنشاء مستخدم بكلمة مرور قوية:
</p>

<pre class="ipsCode">
mysql&gt; <span class="hljs-keyword">CREATE</span> USER <span class="hljs-string">'sammy'</span>@<span class="hljs-string">'localhost'</span> IDENTIFIED <span class="hljs-keyword">BY</span> <span class="hljs-string">'password'</span>;
</pre>

<p>
	ثم امنح الصلاحيات المناسبة للمستخدم الجديد. كمثال، يمكنك منح المستخدم صلاحيات لجميع جداول قاعدة البيانات، بالإضافة إلى إمكانية إضافة وتعديل وحذف صلاحيات المستخدمين باستخدام الأمر التالي:
</p>

<pre class="ipsCode">
mysql&gt; GRANT <span class="hljs-literal">ALL</span> PRIVILEGES <span class="hljs-keyword">ON</span> *.* <span class="hljs-keyword">TO</span> <span class="hljs-string">'sammy'</span>@<span class="hljs-string">'localhost'</span> <span class="hljs-keyword">WITH</span> GRANT OPTION;
</pre>

<p>
	لاحظ أنك لا تحتاج في هذه النقطة لاستخدام أمر <code>FLUSH PRIVILEGES</code> مرة أخرى. تحتاج لاستخدام هذا الأمر فقط عند تعديل جداول منح الصلاحيات باستخدام أحد الأوامر <code>INSERT</code>، أو <code>UPDATE</code>، أو <code>DELETE</code>. ولأنك قمت بإنشاء مستخدم هنا عوضا عن تعديل مستخدم موجود فإن الأمر <code>FLUSH PRIVILEGES</code> غير مهم هنا.
</p>

<p>
	أغلق شاشة اوامر MySQL:
</p>

<pre class="ipsCode">
mysql&gt; <span class="hljs-keyword">exit</span>
</pre>

<p>
	وأخيرا نختبر صحة تثبيت MySQL.
</p>

<h2 id="-4-mysql">
	خطوة 4 - اختبار MySQL
</h2>

<p>
	يجب أن يبدأ MySQL بالعمل تلقائيا بغض النظر عن الطريقة التي قمت بتثبيته بها. للتحقق من ذلك، نقوم بفحص حالته.
</p>

<pre class="ipsCode">
 <span class="hljs-variable">$ </span>systemctl status mysql.service
</pre>

<p>
	سترى مخرجات شبيهة بالمخرجات التالية:
</p>

<pre class="ipsCode">
● mysql.service - MySQL Community Server
<span class="hljs-symbol">
   Loaded:</span> loaded (<span class="hljs-meta-keyword">/lib/</span>systemd<span class="hljs-meta-keyword">/system/</span>mysql.service; enabled; vendor preset: en
<span class="hljs-symbol">
   Active:</span> active (running) since Wed <span class="hljs-number">2018</span><span class="hljs-number">-04</span><span class="hljs-number">-23</span> <span class="hljs-number">21</span>:<span class="hljs-number">21</span>:<span class="hljs-number">25</span> UTC; <span class="hljs-number">30</span>min ago

 Main <abbr title="Process IDentifier | معرّف العملية أو البرنامج">PID</abbr>: <span class="hljs-number">3754</span> (mysqld)
<span class="hljs-symbol">
    Tasks:</span> <span class="hljs-number">28</span>
<span class="hljs-symbol">
   Memory:</span> <span class="hljs-number">142.3</span>M
<span class="hljs-symbol">
      CPU:</span> <span class="hljs-number">1.994</span>s
<span class="hljs-symbol">
   CGroup:</span> /system.slice/mysql.service

           └─<span class="hljs-number">3754</span> <span class="hljs-meta-keyword">/usr/</span>sbin/mysqld
</pre>

<p>
	إن كان MySQL لا يعمل فيمكنك تشغيله باستخدام الأمر <code>sudo systemctl start mysql</code>.
</p>

<p>
	للمزيد من الفحص يمكنك محاولة الاتصال بقاعدة البيانات باستخدام أداة <code>mysqladmin</code> والتي تعتبر أداة عميل تتيح لك تنفيذ أوامر ذات صلاحيات مسؤول. كمثال، الأمر التالي يتصل ب MySQL كمستخدم مسؤول ("<code>‎-u root</code>") ويطلب كلمة مرور ("<code>‎-p</code>") ويعرض الإصدار.
</p>

<pre class="ipsCode">
 $ sudo mysqladmin -<span class="hljs-selector-tag">p</span> -u root version
</pre>

<p>
	يجب أن ترى مخرجات كالتالي:
</p>

<pre class="ipsCode">
mysqladmin  Ver 8.42 Distrib 5.7.21, for Linux on x86_64
Copyright (c) 2000, 2018, Oracle<span class="hljs-built_in"> and/or </span>its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation<span class="hljs-built_in"> and/or </span>its
affiliates. Other names may be trademarks of their respective
owners.

Server version      5.7.21-1ubuntu1
Protocol version    10
Connection      Localhost via UNIX socket
UNIX socket     /var/run/mysqld/mysqld.sock
Uptime:         30 min 54 sec

Threads: 1  Questions: 12  Slow queries: 0  Opens: 115  Flush tables: 1  Open tables: 34  Queries per second avg: 0.006
</pre>

<p>
	هذا يعني أن MySQL يعمل.
</p>

<h2 id="-">
	الخلاصة
</h2>

<p>
	الآن أصبح لديك الإعداد الأولي ل MySQL على الخادم الخاص بك. هنا بعض الأمثلة على بعض الخطوات اللاحقة:
</p>

<ul>
<li>
		<a href="https://academy.hsoub.com/devops/servers/databases/mysql/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%AA%D8%A3%D9%85%D9%8A%D9%86-%D9%82%D9%88%D8%A7%D8%B9%D8%AF-%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-mysql-mariadb-%D8%B9%D9%84%D9%89-%D8%AE%D9%88%D8%A7%D8%AF%D9%8A%D9%85-%D9%84%D9%8A%D9%86%D9%83%D8%B3-r54/" rel="">إعداد بعض الميزات الأمنية الاضافية</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/devops/servers/databases/mysql/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%AA%D8%BA%D9%8A%D9%8A%D8%B1-%D9%85%D8%AC%D9%84%D8%AF-%D8%AA%D8%AE%D8%B2%D9%8A%D9%86-%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-mysql-%D8%A5%D9%84%D9%89-%D9%85%D9%83%D8%A7%D9%86%D9%8D-%D8%A2%D8%AE%D8%B1-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D8%A7%D9%84%D9%88%D8%B5%D9%84%D8%A7%D8%AA-%D8%A7%D9%84%D8%B1%D9%85%D8%B2%D9%8A%D8%A9-r307/" rel="">نقل مجلد البيانات</a>
	</li>
</ul>
<p>
	ترجمة -وبتصرف- للمقال <a href="https://www.digitalocean.com/community/tutorials/how-to-install-mysql-on-ubuntu-18-04" rel="external nofollow">How To Install MySQL on Ubuntu 18.04</a> لصاحبه الكاتب Mark Drake.
</p>
]]></description><guid isPermaLink="false">433</guid><pubDate>Sun, 04 Aug 2019 10:05:35 +0000</pubDate></item><item><title>&#x643;&#x64A;&#x641; &#x62A;&#x634;&#x62E;&#x635; &#x623;&#x62E;&#x637;&#x627;&#x621; &#x627;&#x644;&#x645;&#x642;&#x627;&#x628;&#x633; Sockets &#x641;&#x64A; MySQL</title><link>https://academy.hsoub.com/devops/servers/databases/mysql/%D9%83%D9%8A%D9%81-%D8%AA%D8%B4%D8%AE%D8%B5-%D8%A3%D8%AE%D8%B7%D8%A7%D8%A1-%D8%A7%D9%84%D9%85%D9%82%D8%A7%D8%A8%D8%B3-sockets-%D9%81%D9%8A-mysql-r406/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2019_04/5cb2f26824a2d_-----mysql.jpg.f45f9cf674baae06fa6dfcef618c5490.jpg" /></p>

<p>
	يهدف هذا الدليل إلى أن يكون مصدرًا ونقطة بداية لتشخيص واستكشاف مشاكل وإعدادات MySQL للتمهيد لحلها. سنتناول بعضًا من المشاكل التي يتعرّض لها كثيرون من مستخدمي MySQL ونوفّر إرشادات لكيفية تشخيصها وحلها. سيشتمل الدليل كذلك على روابط لمقالات من أكاديميّة حسوب ومن التوثيق الرسمي للاستفادة منها.
</p>

<ul>
<li>
		<a href="https://academy.hsoub.com/devops/servers/databases/mysql/%D9%83%D9%8A%D9%81-%D8%AA%D8%B9%D8%B1%D8%B6-%D8%B3%D8%AC%D9%84%D8%A7%D8%AA-%D8%A7%D9%84%D8%A3%D8%AE%D8%B7%D8%A7%D8%A1-%D9%88%D8%AA%D8%B4%D8%AE%D8%B5-%D8%A7%D9%84%D8%A7%D8%B3%D8%AA%D8%B9%D9%84%D8%A7%D9%85%D8%A7%D8%AA-%D9%81%D9%8A-mysql-r402/" rel="">كيف تعرض سجلّات الأخطاء وتشخّص الاستعلامات في MySQL</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/devops/servers/databases/mysql/%D9%83%D9%8A%D9%81-%D8%AA%D8%B3%D9%85%D8%AD-%D8%A8%D8%A7%D9%84%D8%A7%D8%AA%D8%B5%D8%A7%D9%84-%D8%B9%D9%86-%D8%A8%D8%B9%D8%AF-%D8%A8%D9%82%D8%A7%D8%B9%D8%AF%D8%A9-%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-mysql-r403/" rel="">كيف تسمح بالاتّصال عن بعد بقاعدة بيانات MySQL</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/devops/servers/databases/mysql/%D9%83%D9%8A%D9%81-%D8%AA%D8%B9%D8%A7%D9%84%D8%AC-%D8%A7%D9%86%D9%87%D9%8A%D8%A7%D8%B1-%D8%AE%D8%A7%D8%AF%D9%88%D9%85-mysql-r404/" rel="">كيف تعالج انهيار خادوم MySQL</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/devops/servers/databases/mysql/%D9%83%D9%8A%D9%81-%D8%AA%D8%B5%D9%84%D8%AD-%D8%A7%D9%84%D8%AC%D8%AF%D8%A7%D9%88%D9%84-%D8%A7%D9%84%D9%85%D8%B9%D8%B7%D9%88%D8%A8%D8%A9-%D9%81%D9%8A-mysql-r405/" rel="">كيف تصلح الجداول المعطوبة في MySQL</a>
	</li>
	<li>
		كيف تشخّص أخطاء المقابس Sockets في MySQL
	</li>
</ul>
<p>
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="29164" href="https://academy.hsoub.com/uploads/monthly_2019_04/5cb2f26c740a5_-----mysql.jpg.14be7a0c0ad133638190fce89945b4fc.jpg" rel=""><img alt="كيف-تشخص-أخطاء-المقابس-في-mysql.jpg" class="ipsImage ipsImage_thumbnailed" data-fileid="29164" data-unique="kdbj3jbsp" src="https://academy.hsoub.com/uploads/monthly_2019_04/5cb2f26c95e69_-----mysql.thumb.jpg.e45f9cc16c99d6a1ba8187ae232c18ed.jpg"></a>
</p>

<p>
	يُدير خادوم MySQL الاتّصالات القادمة إلى قاعدة البيانات اعتمادًا على ملفّ مقبس Socket، وهو نوعٌ خاصّ من الملفّات يسهّل التواصل بين عمليّات Processes مختلفة. يحمل الملفّ المقبس الخاصّ بخادوم MySQL اسمَ <code>mysqld.sock</code> ويوجد عادةً - بالنسبة للخواديم العاملة بتوزيعة أوبنتو – في المجلّد <code>‎/var/run/mysqld/‎</code>. تُنشئ خدمة MySQL هذا الملفّ تلقائيّا.
</p>

<p>
	تتسبّب التعديلات على نظام التشغيل أو على إعدادات MySQL في عدم تمكّن MySQL من قراءة الملفّ المقبس، ممّا يمنع الوصول إلى قواعد البيانات على الخادوم. يظهر خطأ المقبس الشائع على النحو التالي:
</p>

<pre class="ipsCode" id="ips_uid_7795_14">
ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2)
</pre>

<p>
	توجد بضعة أمور تتسبّب في الخطأ أعلاه، وخيّارات محدودة لإصلاحه.
</p>

<p>
	أحد الأسباب الشائعة هي توقيف خدمة MySQL أو الإخفاق في تشغيلها؛ بمعنى أنّ الخدمة لم تستطع إنشاء الملفّ المقبس ابتداءً. حاول تشغيل الخدمة بالأداة <code>systemctl</code> لمعرفة ما إذا كان هذا هو سبب ظهور الخطأ:
</p>

<pre class="ipsCode" id="ips_uid_7795_16">
sudo systemctl start mysql
</pre>

<p>
	ثم حاول الوصول إلى سطر أوامر MySQL من جديد. تأكّد - إن استمرّ الخطأ في الظهور – من المسار الذي يبحث فيه MySQL عن الملفّ المقبس. يمكن معرفة هذا المسار من خلال ملفّ الإعداد <code>mysqld.cnf</code>:
</p>

<pre class="ipsCode" id="ips_uid_7795_18">
sudo nano /etc/mysql/mysql.conf.d/mysql.cnf
</pre>

<p>
	ابحث عن المُعامل <code>socket</code> ضمن المقطع <code>[mysqld]</code> من الملفّ. يبدو المقطع المذكور كالتالي:
</p>

<pre class="ipsCode" id="ips_uid_7795_20">
. . .
[mysqld]
user            = mysql
pid-file        = /var/run/mysqld/mysqld.pid
socket          = /var/run/mysqld/mysqld.sock
port            = 3306
. . .
</pre>

<p>
	أغلق الملفّ ثم تأكّد من وجود الملفّ <code>mysqld.sock</code> بتنفيذ الأمر <code>ls</code> على المسار الذي يتوقّع MySQL وجودَ الملفّ فيه:
</p>

<pre class="ipsCode" id="ips_uid_7795_22">
ls -a /var/run/mysqld/
</pre>

<p>
	إذا كان الملفّ المقبس موجودًا فسيظهر في مُخرجات الأمر:
</p>

<pre class="ipsCode" id="ips_uid_7795_24">
.  ..  mysqld.pid  mysqld.sock  mysqld.sock.lock
</pre>

<p>
	إذا لم يكن الملفّ موجودًا فربما يكون السبب هو أنّ MySQL يحاول إنشاءه دون أن تكون لديه الصلاحيّات المناسبة لذلك. يمكن التأكّد صحّة الصلاحيّات بتغيير ملكيّة المجلّد إلى المستخدم والمجموعة <code>mysql</code>:
</p>

<pre class="ipsCode">
sudo chown <span class="hljs-string">mysql:</span>mysql <span class="hljs-regexp">/var/</span>run<span class="hljs-regexp">/mysqld/</span>
</pre>

<p>
	ثم تأكّد بعد ذلك من أنّ المستخدم <code>mysql</code> لديه الصلاحيّات المناسبة على المجلّد. تصلُح الصلاحيّات <code>755</code> لأغلب الحالات:
</p>

<pre class="ipsCode" id="ips_uid_7795_26">
sudo chmod -R 755 /var/run/mysqld/
</pre>

<p>
	أخيرًا؛ أعد تشغيل MySQL لترى ما إذا كان يستطيع إنشاء الملفّ المقبس من جديد:
</p>

<pre class="ipsCode" id="ips_uid_7795_28">
sudo systemctl restart mysql
</pre>

<p>
	ثم حاول الوصول إلى سطر أوامر MySQL. إن استمرّ خطأ المقبس في الظهور، فقد يشير ذلك إلى وجود مشكلة أعمق في خادوم MySQL، وفي هذه الحالة تجب مراجعة سجلّات الأخطاء بحثًا عن ما يقود إلى معرفة سبب المشكلة.
</p>

<p>
	ترجمة – بتصرّف – للمقال <a href="https://www.digitalocean.com/community/tutorials/how-to-troubleshoot-socket-errors-in-mysql" rel="external nofollow">How To Troubleshoot Socket Errors in MySQL</a> لصاحبه Mark Drake.
</p>

<h2 id="-">
	اقرأ أيضًا
</h2>

<ul>
<li>
		<a href="https://academy.hsoub.com/devops/servers/databases/mysql/%D9%83%D9%8A%D9%81-%D8%AA%D8%B9%D8%B1%D8%B6-%D8%B3%D8%AC%D9%84%D8%A7%D8%AA-%D8%A7%D9%84%D8%A3%D8%AE%D8%B7%D8%A7%D8%A1-%D9%88%D8%AA%D8%B4%D8%AE%D8%B5-%D8%A7%D9%84%D8%A7%D8%B3%D8%AA%D8%B9%D9%84%D8%A7%D9%85%D8%A7%D8%AA-%D9%81%D9%8A-mysql-r402/" rel="">كيف تعرض سجلّات الأخطاء وتشخّص الاستعلامات في MySQL</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/devops/servers/databases/mysql/%D9%83%D9%8A%D9%81-%D8%AA%D8%B3%D9%85%D8%AD-%D8%A8%D8%A7%D9%84%D8%A7%D8%AA%D8%B5%D8%A7%D9%84-%D8%B9%D9%86-%D8%A8%D8%B9%D8%AF-%D8%A8%D9%82%D8%A7%D8%B9%D8%AF%D8%A9-%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-mysql-r403/" rel="">كيف تسمح بالاتّصال عن بعد بقاعدة بيانات MySQL</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/devops/servers/databases/mysql/%D9%83%D9%8A%D9%81-%D8%AA%D8%B9%D8%A7%D9%84%D8%AC-%D8%A7%D9%86%D9%87%D9%8A%D8%A7%D8%B1-%D8%AE%D8%A7%D8%AF%D9%88%D9%85-mysql-r404/" rel="">كيف تعالج انهيار خادوم MySQL</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/devops/servers/databases/mysql/%D9%83%D9%8A%D9%81-%D8%AA%D8%B5%D9%84%D8%AD-%D8%A7%D9%84%D8%AC%D8%AF%D8%A7%D9%88%D9%84-%D8%A7%D9%84%D9%85%D8%B9%D8%B7%D9%88%D8%A8%D8%A9-%D9%81%D9%8A-mysql-r405/" rel="">كيف تصلح الجداول المعطوبة في MySQL</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">406</guid><pubDate>Sun, 14 Apr 2019 10:10:42 +0000</pubDate></item><item><title>&#x643;&#x64A;&#x641; &#x62A;&#x635;&#x644;&#x62D; &#x627;&#x644;&#x62C;&#x62F;&#x627;&#x648;&#x644; &#x627;&#x644;&#x645;&#x639;&#x637;&#x648;&#x628;&#x629; &#x641;&#x64A; MySQL</title><link>https://academy.hsoub.com/devops/servers/databases/mysql/%D9%83%D9%8A%D9%81-%D8%AA%D8%B5%D9%84%D8%AD-%D8%A7%D9%84%D8%AC%D8%AF%D8%A7%D9%88%D9%84-%D8%A7%D9%84%D9%85%D8%B9%D8%B7%D9%88%D8%A8%D8%A9-%D9%81%D9%8A-mysql-r405/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2019_06/5d08cb0f6e071_.jpg.6357c77b3c9ecf732cff6d0402f689ad.jpg" /></p>

<p>
	يهدف هذا الدليل إلى أن يكون مصدرًا ونقطة بداية لتشخيص واستكشاف مشاكل وإعدادات MySQL للتمهيد لحلها. سنتناول بعضًا من المشاكل التي يتعرّض لها كثيرون من مستخدمي MySQL ونوفّر إرشادات لكيفية تشخيصها وحلها. سيشتمل الدليل كذلك على روابط لمقالات من أكاديميّة حسوب ومن التوثيق الرسمي للاستفادة منها.
</p>

<ul>
<li>
		<a href="https://academy.hsoub.com/devops/servers/databases/mysql/%D9%83%D9%8A%D9%81-%D8%AA%D8%B9%D8%B1%D8%B6-%D8%B3%D8%AC%D9%84%D8%A7%D8%AA-%D8%A7%D9%84%D8%A3%D8%AE%D8%B7%D8%A7%D8%A1-%D9%88%D8%AA%D8%B4%D8%AE%D8%B5-%D8%A7%D9%84%D8%A7%D8%B3%D8%AA%D8%B9%D9%84%D8%A7%D9%85%D8%A7%D8%AA-%D9%81%D9%8A-mysql-r402/" rel="">كيف تعرض سجلّات الأخطاء وتشخّص الاستعلامات في MySQL</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/devops/servers/databases/mysql/%D9%83%D9%8A%D9%81-%D8%AA%D8%B3%D9%85%D8%AD-%D8%A8%D8%A7%D9%84%D8%A7%D8%AA%D8%B5%D8%A7%D9%84-%D8%B9%D9%86-%D8%A8%D8%B9%D8%AF-%D8%A8%D9%82%D8%A7%D8%B9%D8%AF%D8%A9-%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-mysql-r403/" rel="">كيف تسمح بالاتّصال عن بعد بقاعدة بيانات MySQL</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/devops/servers/databases/mysql/%D9%83%D9%8A%D9%81-%D8%AA%D8%B9%D8%A7%D9%84%D8%AC-%D8%A7%D9%86%D9%87%D9%8A%D8%A7%D8%B1-%D8%AE%D8%A7%D8%AF%D9%88%D9%85-mysql-r404/" rel="">كيف تعالج انهيار خادوم MySQL</a>
	</li>
	<li>
		كيف تصلح الجداول المعطوبة في MySQL
	</li>
	<li>
		<a href="https://academy.hsoub.com/devops/servers/databases/mysql/%D9%83%D9%8A%D9%81-%D8%AA%D8%B5%D9%84%D8%AD-%D8%A7%D9%84%D8%AC%D8%AF%D8%A7%D9%88%D9%84-%D8%A7%D9%84%D9%85%D8%B9%D8%B7%D9%88%D8%A8%D8%A9-%D9%81%D9%8A-mysql-r405/" rel="">كيف تشخّص أخطاء المقابس Sockets في MySQL</a>
	</li>
</ul>
<p>
	 
</p>

<p>
	<a class="ipsAttachLink ipsAttachLink_image" href="https://academy.hsoub.com/uploads/monthly_2019_06/5d08cb1307763_.jpg.b30dc1d63aaabc9d989c8de89fbb5fb3.jpg" data-fileid="30255" rel=""><img class="ipsImage ipsImage_thumbnailed" data-fileid="30255" data-unique="p9snoec1c" src="https://academy.hsoub.com/uploads/monthly_2019_06/5d08cb1329852_.thumb.jpg.f4ff9208274881d86b83c7aa1090c83f.jpg" alt="كيف تصلح الجداول المعطوبة.jpg"></a>
</p>

<p>
	يحدُث أحيانًا أن تُصاب جداول MySQL بأعطاب سببها أخطاء أدّت إلى استحالة قراءة البيانات الموجودة بها. تؤدّي محاولة قراءة بيانات من جداول معطوبة – عادةً - إلى انهيّار الخادوم.
</p>

<p>
	في ما يلي بعضٌ من الأسباب الشائعة لعطب الجداول:
</p>

<ul>
<li>
		توقّف خادوم MySQL أثناء عمليّة كتابة في جدول.
	</li>
	<li>
		التعديل، من طرف برنامج خارجي، على جدول يُعدِّل عليه الخادوم في نفس الوقت.
	</li>
	<li>
		إيقاف الخادوم دون سابق إنذار.
	</li>
	<li>
		إخفاق في عتاد الحاسوب.
	</li>
	<li>
		وجود علّة في برمجة MySQL.
	</li>
</ul>
<p>
	إذا كنت تظنّ أنّ أحد جداول قاعدة البيانات معطوب، فيجب أخذ <a href="https://academy.hsoub.com/devops/servers/databases/mysql/%D9%83%D9%8A%D9%81-%D8%AA%D9%82%D9%88%D9%85-%D8%A8%D8%A7%D9%84%D9%86%D8%B3%D8%AE-%D8%A7%D9%84%D8%A7%D8%AD%D8%AA%D9%8A%D8%A7%D8%B7%D9%8A-%D9%84%D9%82%D9%88%D8%A7%D8%B9%D8%AF-%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-mysql-%D8%B9%D9%84%D9%89-ubuntu-r110/" rel="">نسخة احتيّاطيّة</a> من مجلّد البيانات قبل تشخيص عطب الجدول أو محاولة إصلاحه.يُساعد هذا الإجراء في التقليل من خطر فقد البيانات. أول ما يجب عليك فعلُه هو إيقاف خدمة MySQL:
</p>

<pre class="ipsCode" id="ips_uid_1133_9">
sudo systemctl stop mysql
</pre>

<p>
	ثم نقل جميع بيانات MySQL إلى مجلّد جديد. يوجد المجلّد المبدئي لبيانات MySQL بالنسبة للخواديم العاملة بتوزيعة أوبونتو في المسار <code>‎/var/lib/mysql/‎</code>:
</p>

<pre class="ipsCode" id="ips_uid_1133_11">
cp -r /var/lib/mysql /var/lib/mysql_bkp
</pre>

<p>
	تصبح جاهزًا – بعد إنشاء نسخة احتيّاطيّة – للبدء في التحقيق لمعرفة ما إذا كان الجدول معطوبًا أم لا. إذا كان الجدول يستخدم <a href="https://dev.mysql.com/doc/refman/5.7/en/myisam-storage-engine.html" rel="external nofollow">محرّك التخزين (MyISAM)</a> فيمكن التحقّق من عطب الجدول باستخدام التعليمة <code>CHECK TABLE</code> من سطر أوامر MySQL:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_1133_13" style="">
<span class="pln">CHECK TABLE table_name</span><span class="pun">;</span></pre>

<p>
	ستظهر رسالة في مُخرجات الأمر تخبرك ما إذا كان الجدول معطوبًا أم لا. إذا كان جدول MyISAM معطوبًا فيمكن عادةً إصلاحه بتنفيذ التعليمة <code>REPAIR TABLE</code>:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_1133_15" style="">
<span class="pln">REPAIR TABLE table_name</span><span class="pun">;</span></pre>

<p>
	ستُظهرمخرجات التعليمة - بافتراض أنّ عمليّة الإصلاح ناجحة – رسالة تشبه التالي:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_1133_17" style="">
<span class="pun">+--------------------------+--------+----------+----------+</span><span class="pln">
</span><span class="pun">|</span><span class="pln"> </span><span class="typ">Table</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="typ">Op</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="typ">Msg_type</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="typ">Msg_text</span><span class="pln"> </span><span class="pun">|</span><span class="pln">
</span><span class="pun">+--------------------------+--------+----------+----------+</span><span class="pln">
</span><span class="pun">|</span><span class="pln"> database_name</span><span class="pun">.</span><span class="pln">table_name </span><span class="pun">|</span><span class="pln"> repair </span><span class="pun">|</span><span class="pln"> status </span><span class="pun">|</span><span class="pln"> OK </span><span class="pun">|</span><span class="pln">
</span><span class="pun">+--------------------------+--------+----------+----------+</span></pre>

<p>
	أما إذا لم تنجح العمليّة وبقي الجدول معطوبًا فإنّ توثيق MySQL يقترح بضعة طرق بديلة من أجل إصلاح الجداول المعطوبة. بالنسبة للجداول التي تستخدم <a href="https://dev.mysql.com/doc/refman/5.7/en/innodb-storage-engine.html" rel="external nofollow">محرّك التخزين InnoDB</a>، فعمليّة الإصلاح مختلفة. بدأت قواعد بيانات MySQL باستخدام محرّك InnoDB - الذي يتميّز بتوفّرعمليّات التحقّق التلقائي من الأعطال وإصلاحها - مبدئيًّا منذ الإصدر 5.5. يتحقّق InnoDB من وجود أعطال في الصفحات بحساب مجموع تحقّق (Checksum) لكلّ صفحة يقرأها؛ وفي حال وجود اختلاف بين مجموعات التحقّق فإنّه يوقف خادوم MySQL تلقائيّا.
</p>

<p>
	نادرًا مّا توجد حاجة لإصلاح الأعطاب في الجداول التي تستخدم InnoDB، إذ أنّ InnoDB لديه آليّة يمكنها حلّ أغلب الأعطاب عند إعادة تشغيل الخادوم. على الرغم من ذلك، ينصح توثيق MySQL باستخدام <a href="https://dev.mysql.com/doc/refman/5.7/en/rebuilding-tables.html#rebuilding-tables-dump-reload" rel="external nofollow">طريقة "الطرح وإعادة التحميل" Dump and reload</a>. يعني هذا إعادة الوصول إلى الجدول المعطوب باستخدام الأداة <code>mysqldump</code>، لإنشاء <a href="https://dev.mysql.com/doc/refman/5.7/en/glossary.html#glos_logical_backup" rel="external nofollow">نسخة احتيّاطيّة منطقيّة</a> من الجدول يُحتَفظ فيها ببُنيته وبياناته؛ ثم إعادة تحميل الجدول إلى قاعدة البيانات. حاول إعادة تشغيل خدمة MySQL لترى إن كنت ستتمكّن من الوصول إلى الخادوم، مع استحضار آلية عمل طريقة "الطرح وإعادة التحميل:
</p>

<pre class="ipsCode" id="ips_uid_1133_19">
sudo systemctl restart mysql
</pre>

<p>
	إنْ استمرّ انهيّار الخادوم أو استحال الوصول إليه لسبب آخر، فربّما يكون من المفيد تفعيل الخيّار <code>force_recovery</code> ضمن عدادات InnoDB. يمكن فعلُ ذلك بسهولة عبر تحرير الملفّ <code>mysqld.cnf</code>:
</p>

<pre class="ipsCode" id="ips_uid_1133_21">
sudo nano /etc/mysql/mysql.conf.d/mysqld.cnf
</pre>

<p>
	أضف السّطر التالي في المقطع <code>[mysqld]</code> من الملفّ:
</p>

<pre class="ipsCode" id="ips_uid_1133_23">
. . .
[mysqld]
. . .
innodb_force_recovery=1
</pre>

<p>
	احفظ الملفّ ثم أغلقه، ثم جرّب إعادة تشغيل MySQL من جديد. إذا استطعت النجاح في الوصول إلى الجدول المعطوب فاستخدم الأداة <code>mysqldump</code> لطرح بيانات الجدول في ملفّ جديد. يمكنك تسميّة الملفّ بما يحلو لك. في ما يلي اخترنا الاسم <code>out.sql</code>:
</p>

<pre class="ipsCode" id="ips_uid_1133_25">
mysqldump database_name table_name &gt; out.sql
</pre>

<p>
	الخطوة المواليّة هي حذف الجدول من قاعدة البيانات. يمكنك استخدام الصيغة التاليّة لتفادي فتح سطرأوامر MySQL من جديد:
</p>

<pre class="ipsCode">
mysql -u <span class="hljs-keyword">user</span> <span class="hljs-title">-p</span> --<span class="hljs-attr">execute=</span><span class="hljs-string">"DROP TABLE database_name.table_name"</span>
</pre>

<p>
	أخيرًا، استعد الجدول بالاعتماد على ملفّ الطرح الذي أنشاته للتو:
</p>

<pre class="ipsCode" id="ips_uid_1133_27">
mysql -u user -p &lt; out.sql
</pre>

<p>
	فليكن في علمك أن محرّك التخزين InnoDB – في العموم – أكثر مقاومةً للأخطاء من محركّ التخزين القديم MyISAM. لا يعني هذا أنّ جداول InnoDB غير معرَّضة للأخطاء، لكن وجود ميزات التغلّب على الأخطاء تلقائيّا يجعل احتمال عطب الجداول وما ينتج عنه من انهيّارات أقلّ بكثير.
</p>

<p>
	ترجمة - بتصرّف - للمقال <a href="https://www.digitalocean.com/community/tutorials/how-to-fix-corrupted-tables-in-mysql" rel="external nofollow">How To Fix Corrupted Tables in MySQL</a> لصاحبه Mark Drake.
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
<li>
		المقال التالي: كيف تشخّص أخطاء المقابس Sockets في MySQL
	</li>
</ul>
]]></description><guid isPermaLink="false">405</guid><pubDate>Sun, 05 May 2019 13:09:00 +0000</pubDate></item><item><title>&#x643;&#x64A;&#x641; &#x62A;&#x639;&#x627;&#x644;&#x62C; &#x627;&#x646;&#x647;&#x64A;&#x627;&#x631; &#x62E;&#x627;&#x62F;&#x648;&#x645; MySQL</title><link>https://academy.hsoub.com/devops/servers/databases/mysql/%D9%83%D9%8A%D9%81-%D8%AA%D8%B9%D8%A7%D9%84%D8%AC-%D8%A7%D9%86%D9%87%D9%8A%D8%A7%D8%B1-%D8%AE%D8%A7%D8%AF%D9%88%D9%85-mysql-r404/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2019_04/5cb2eeb7a955d_---mysql.jpg.b046fcd395ad27173686404b4897cd6d.jpg" /></p>

<p>
	يهدف هذا الدليل إلى أن يكون مصدرًا ونقطة بداية لتشخيص واستكشاف مشاكل وإعدادات MySQL للتمهيد لحلها. سنتناول بعضًا من المشاكل التي يتعرّض لها كثيرون من مستخدمي MySQL ونوفّر إرشادات لكيفية تشخيصها وحلها. سيشتمل الدليل كذلك على روابط لمقالات من أكاديميّة حسوب ومن التوثيق الرسمي للاستفادة منها.
</p>

<ul>
<li>
		<a href="https://academy.hsoub.com/devops/servers/databases/mysql/%D9%83%D9%8A%D9%81-%D8%AA%D8%B9%D8%B1%D8%B6-%D8%B3%D8%AC%D9%84%D8%A7%D8%AA-%D8%A7%D9%84%D8%A3%D8%AE%D8%B7%D8%A7%D8%A1-%D9%88%D8%AA%D8%B4%D8%AE%D8%B5-%D8%A7%D9%84%D8%A7%D8%B3%D8%AA%D8%B9%D9%84%D8%A7%D9%85%D8%A7%D8%AA-%D9%81%D9%8A-mysql-r402/" rel="">كيف تعرض سجلّات الأخطاء وتشخّص الاستعلامات في MySQL</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/devops/servers/databases/mysql/%D9%83%D9%8A%D9%81-%D8%AA%D8%B3%D9%85%D8%AD-%D8%A8%D8%A7%D9%84%D8%A7%D8%AA%D8%B5%D8%A7%D9%84-%D8%B9%D9%86-%D8%A8%D8%B9%D8%AF-%D8%A8%D9%82%D8%A7%D8%B9%D8%AF%D8%A9-%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-mysql-r403/" rel="">كيف تسمح بالاتّصال عن بعد بقاعدة بيانات MySQL</a>
	</li>
	<li>
		كيف تعالج انهيار خادوم MySQL
	</li>
	<li>
		<a href="https://academy.hsoub.com/devops/servers/databases/mysql/%D9%83%D9%8A%D9%81-%D8%AA%D8%B5%D9%84%D8%AD-%D8%A7%D9%84%D8%AC%D8%AF%D8%A7%D9%88%D9%84-%D8%A7%D9%84%D9%85%D8%B9%D8%B7%D9%88%D8%A8%D8%A9-%D9%81%D9%8A-mysql-r405/" rel="">كيف تصلح الجداول المعطوبة في MySQL</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/devops/servers/databases/mysql/%D9%83%D9%8A%D9%81-%D8%AA%D8%B4%D8%AE%D8%B5-%D8%A3%D8%AE%D8%B7%D8%A7%D8%A1-%D8%A7%D9%84%D9%85%D9%82%D8%A7%D8%A8%D8%B3-sockets-%D9%81%D9%8A-mysql-r406/" rel="">كيف تشخّص أخطاء المقابس Sockets في MySQL</a>
	</li>
</ul>
<p>
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="29162" href="https://academy.hsoub.com/uploads/monthly_2019_04/5cb2eec0e12f9_---mysql.jpg.7e6e7740061383c017a9188cedada9b8.jpg" rel=""><img alt="كيف-تعالج-خادم-mysql.jpg" class="ipsImage ipsImage_thumbnailed" data-fileid="29162" data-unique="pawc1hpu7" src="https://academy.hsoub.com/uploads/monthly_2019_04/5cb2eec11701d_---mysql.thumb.jpg.33609c86c905eaf02fed63b1a030938a.jpg"></a>
</p>

<p>
	يعدّ التوقّف عن العمل، أو الإخفاق في تشغيل الخدمة بسبب نقص حجم الذاكرة، أكثرَ أسباب الانهيّارات التي تواجهها MySQL شيوعا. ستحتاج – من أجل التحقّق من الأمر – إلى مراجعة سجل أخطاء MySQL بعد الانهيار.
</p>

<p>
	أوّلًا، ابدأ بمحاولة تشغيل خادوم MySQL بكتابة الأمر:
</p>

<pre class="ipsCode" id="ips_uid_446_10">
sudo systemctl start mysql
</pre>

<p>
	ثم راجع سجلّات الأخطاء لمعرفة سبب انهيّار MySQL. يمكن استخدام الأمر <code>less</code> لمراجعة السجلّات صفحةً صفحة:
</p>

<pre class="ipsCode" id="ips_uid_446_12">
sudo less /var/log/mysql/error.log
</pre>

<p>
	رسالتا الخطأ <code>Out of memory</code> و <code>mmap can’t allocate</code> من الرسائل الشائعة التي تنمّ عن نقص في الذاكرة. في ما يلي بعضٌ من الحلول المحتملة لنقص حجم الذاكرة:
</p>

<ul>
<li>
		<strong>تحسين إعدادات MySQL</strong>. الأداة مفتوحة المصدر <a href="https://github.com/major/MySQLTuner-perl" rel="external nofollow">MySQLtuner</a> رائعة لهذا الغرض. يؤدّي تنفيذ سكربت MySQLtuner إلى إظهار مجموعة من التعديلات الموصى بإجرائها على ملف إعدادات MySQL‏ (<code>mysqld.cnf</code>). يُرجى الانتباه إلى أنّه كل ما طالت مدّة تشغيل خادوم MySQL قبل استخدام MySQLTuner كانت اقتراحات السكريبت أحسن. استخدم <a href="http://www.mysqlcalculator.com/" rel="external nofollow">حاسبة MySQL هذه</a> لتقدير حجم الذاكرة المطلوب بالنسبة لكلّ من إعداداتك الحاليّة وتلك التي يقترحها MySQLtuner.
	</li>
	<li>
		<strong>التقليل من اعتماد تطبيق الويب على MySQL في تنزيل الصفحات</strong>. إضافة نظام تخزين مؤقّت (Cache) إلى التطبيق هو الوسيلة المعتادة لهذا الأمر. من أمثلة استخدام هذه الطريقة نظامُ Joomla الذي يتضمّن وظيفة تخبئة مُضمَّنة يمكن تفعيلها، والإضافة <a href="https://wordpress.org/plugins/wp-super-cache/" rel="external nofollow">WP Super Cache</a> التي تضيف خاصيّة التخبئة إلى ووردبريس.
	</li>
	<li>
		<strong>الترقيّة إلى خادوم افتراضي ذي قدرات أكبر</strong>. يُنصَح بخادوم لا تقلّ ذاكرة الوصول العشوائي فيه عن 1GB مهما كانت نوعيّة استخدام قاعدة البيانات MySQL، إلّا أنّ حجم البيانات ونوعيّتها يمكن أن يؤثر كثيرًا على متطلّبات الذاكرة. يُرجى الانتباه إلى أنّ ترقيّة الخادوم، رغم أنّها من المرجّح أن تحلّ المشكلة، إلّا أنه حلّ لا يُنصَح به إلّا بعد التحقّق من الخيّارات الأخرى ومعرفة احتمالات نجاحها. تكلّف إضافة قدرات أكبر إلى الخادوم سعرًا أعلى ويجدر بك اعتماد هذا الخيّار إلّا إذا كان الحلّ الأمثل في نهاية المطاف. انتبه أيضًا إلى أنّ <a href="https://dev.mysql.com/doc/refman/5.7/en/crashing.html" rel="external nofollow">توثيق MySQL </a> يتضمّن اقتراحات أخرى لتشخيص الانهيّارات ومنع حدوثها.
	</li>
</ul>
<p>
	ترجمة – بتصرّف – للمقال <a href="https://www.digitalocean.com/community/tutorials/how-to-address-crashes-in-mysql" rel="external nofollow">How To Address Crashes in MySQL </a> لصاحبه Mark Drake.
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
<li>
		المقال التالي: <a href="https://academy.hsoub.com/devops/servers/databases/mysql/%D9%83%D9%8A%D9%81-%D8%AA%D8%B5%D9%84%D8%AD-%D8%A7%D9%84%D8%AC%D8%AF%D8%A7%D9%88%D9%84-%D8%A7%D9%84%D9%85%D8%B9%D8%B7%D9%88%D8%A8%D8%A9-%D9%81%D9%8A-mysql-r405/" rel="">كيف تصلح الجداول المعطوبة في MySQL</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">404</guid><pubDate>Sun, 14 Apr 2019 10:10:39 +0000</pubDate></item><item><title>&#x643;&#x64A;&#x641; &#x62A;&#x633;&#x645;&#x62D; &#x628;&#x627;&#x644;&#x627;&#x62A;&#x635;&#x627;&#x644; &#x639;&#x646; &#x628;&#x639;&#x62F; &#x628;&#x642;&#x627;&#x639;&#x62F;&#x629; &#x628;&#x64A;&#x627;&#x646;&#x627;&#x62A; MySQL</title><link>https://academy.hsoub.com/devops/servers/databases/mysql/%D9%83%D9%8A%D9%81-%D8%AA%D8%B3%D9%85%D8%AD-%D8%A8%D8%A7%D9%84%D8%A7%D8%AA%D8%B5%D8%A7%D9%84-%D8%B9%D9%86-%D8%A8%D8%B9%D8%AF-%D8%A8%D9%82%D8%A7%D8%B9%D8%AF%D8%A9-%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-mysql-r403/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2019_04/5cb2e9d1876da_-------mysql.jpg.29772e0f2cea16fd1b589c2f0e59f5b2.jpg" /></p>

<p>
	يهدف هذا الدليل إلى أن يكون مصدرًا ونقطة بداية لتشخيص واستكشاف مشاكل وإعدادات MySQL للتمهيد لحلها. سنتناول بعضًا من المشاكل التي يتعرّض لها كثيرون من مستخدمي MySQL ونوفّر إرشادات لكيفية تشخيصها وحلها. سيشتمل الدليل كذلك على روابط لمقالات من أكاديميّة حسوب ومن التوثيق الرسمي للاستفادة منها.
</p>

<ul>
<li>
		<a href="https://academy.hsoub.com/devops/servers/databases/mysql/%D9%83%D9%8A%D9%81-%D8%AA%D8%B9%D8%B1%D8%B6-%D8%B3%D8%AC%D9%84%D8%A7%D8%AA-%D8%A7%D9%84%D8%A3%D8%AE%D8%B7%D8%A7%D8%A1-%D9%88%D8%AA%D8%B4%D8%AE%D8%B5-%D8%A7%D9%84%D8%A7%D8%B3%D8%AA%D8%B9%D9%84%D8%A7%D9%85%D8%A7%D8%AA-%D9%81%D9%8A-mysql-r402/" rel="">كيف تعرض سجلّات الأخطاء وتشخّص الاستعلامات في MySQL</a>
	</li>
	<li>
		كيف تسمح بالاتّصال عن بعد بقاعدة بيانات MySQL
	</li>
	<li>
		<a href="https://academy.hsoub.com/devops/servers/databases/mysql/%D9%83%D9%8A%D9%81-%D8%AA%D8%B9%D8%A7%D9%84%D8%AC-%D8%A7%D9%86%D9%87%D9%8A%D8%A7%D8%B1-%D8%AE%D8%A7%D8%AF%D9%88%D9%85-mysql-r404/" rel="">كيف تعالج انهيار خادوم MySQL</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/devops/servers/databases/mysql/%D9%83%D9%8A%D9%81-%D8%AA%D8%B5%D9%84%D8%AD-%D8%A7%D9%84%D8%AC%D8%AF%D8%A7%D9%88%D9%84-%D8%A7%D9%84%D9%85%D8%B9%D8%B7%D9%88%D8%A8%D8%A9-%D9%81%D9%8A-mysql-r405/" rel="">كيف تصلح الجداول المعطوبة في MySQL</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/devops/servers/databases/mysql/%D9%83%D9%8A%D9%81-%D8%AA%D8%B4%D8%AE%D8%B5-%D8%A3%D8%AE%D8%B7%D8%A7%D8%A1-%D8%A7%D9%84%D9%85%D9%82%D8%A7%D8%A8%D8%B3-sockets-%D9%81%D9%8A-mysql-r406/" rel="">كيف تشخّص أخطاء المقابس Sockets في MySQL</a>
	</li>
</ul>
<p>
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="29160" href="https://academy.hsoub.com/uploads/monthly_2019_04/5cb2ead196f10_-------mysql.jpg.20f7af16c18320ac79da6dd80a99955a.jpg" rel=""><img alt="كيف-تسمح-بالاتصال-عن-بعد-بقاعدة-بيانات-mysql.jpg" class="ipsImage ipsImage_thumbnailed" data-fileid="29160" data-unique="ugydk5uri" src="https://academy.hsoub.com/uploads/monthly_2019_04/5cb2ead1b97f8_-------mysql.thumb.jpg.b6831919d8d1df486bcb903ce915d65c.jpg"></a>
</p>

<p>
	تبدأ الكثير من المواقع والتطبيقات بوضع خادوم الويب وقاعدة البيانات على نفس النظام؛ إلّا أنّ هذا الإعداد يصبح مع الوقت ثقيلًا وغير قابل للتوسيع.. من الشائع التغلّب على هذا الإشكال بفصل الوظيفتيْن بضبط قاعدة بيانات منفصلة ممّا يسمح لخادوم الوِيب وقاعدة البيانات بالنموّ على الأجهزة الخاصّة بها، كلّ حسب حاجته. يعدّ الإعداد المبدئيّ لـ MySQL الذي لا يسمح سوى بالاتّصالات القادمة من نفس الجهاز، وبالتالي يمنع الاتّصالات القادمة من نظام آخر، أحد المشاكل الشائعة التي يواجهها المستخدمون أثناء محاولة إعداد الوصول إلى MySQL عن بعد. يمكن تعديل السلوك المبدئيّ لـ MySQL بتحرير الملف <code>mysqld.cnf</code>:
</p>

<pre class="ipsCode" id="ips_uid_521_7">
sudo nano /etc/mysql/mysql.conf.d/mysqld.cnf
</pre>

<p>
	انتقل إلى السطر الذي يبدأ بالتوجيه <code>bind-address</code>. يبدو الملفّ على النحو التالي:
</p>

<pre class="ipsCode" id="ips_uid_521_9">
. . .
lc-messages-dir = /usr/share/mysql
skip-external-locking
#
# Instead of skip-networking the default is now to listen only on
# localhost which is more compatible and is not less secure.
bind-address            = 127.0.0.1
. . .
</pre>

<p>
	يأخذ التوجيه مبدئيًّا القيمة <code>127.0.0.1</code>، ممّا يعني أنّ الخادوم سيبحث عن الاتّصالات المحليّة فقط. ستحتاج لتعديل هذه القيمة لتكون عنوان IP خارجي (عنوان الجهاز الذي تريد التواصل معه). كما يمكن استخدام حرف بدل (Wildcard) لأغراض التشخيص والبحث عن الأخطاء. مثلًا: <code>*</code>، أو <code>::</code>، أو <code>0.0.0.0</code>:
</p>

<pre class="ipsCode" id="ips_uid_521_11">
. . .
lc-messages-dir = /usr/share/mysql
skip-external-locking
#
# Instead of skip-networking the default is now to listen only on
# localhost which is more compatible and is not less secure.
bind-address            = 0.0.0.0
. . .
</pre>

<p>
	<strong>ملحوظة:</strong> لا يحتوي الملف <code>mysqld.cnf</code> في الإصدار 8 وما بعده من MySQL – مبدئيًّا – على التوجيه <code>bind-address</code>؛ لذا تجب إضافة التوجيه أسفل آخر سطر من الملفّ على النحو التالي:
</p>

<pre class="ipsCode" id="ips_uid_521_13">
[mysqld]
pid-file        = /var/run/mysqld/mysqld.pid
socket          = /var/run/mysqld/mysqld.sock
datadir         = /var/lib/mysql
log-error       = /var/log/mysql/error.log
bind-address            = 0.0.0.0
</pre>

<p>
	احفظ الملفّ بعد تعديله، ثم أغلقه وأعد تشغيل خدمة MySQL:
</p>

<pre class="ipsCode" id="ips_uid_521_15">
sudo systemctl restart mysql
</pre>

<p>
	حاول بعد ذلك الوصول إلى قاعدة البيانات من جهاز آخر كما يلي (حيث <code>database_server_ip</code> عنوان IP الخاص بخادوم قاعدة البيانات):
</p>

<pre class="ipsCode" id="ips_uid_521_19">
mysql -u user -h database_server_ip -p</pre>

<p>
	إن استطعت الاتّصال بقاعدة البيانات، فهذا يؤكّد أن التوجيه <code>bind-address</code> كان السبب في تعذّر الاتّصال عن بعد بقاعدة البيانات. يُرجى ملاحظة أن القيمة <code>0.0.0.0</code> غير آمنة وتتيح الاتّصال بقاعدة البيانات من جميع عناوين IP. أمّا إن لم تستطع الاتّصال بقاعدة البيانات بعد ضبط إعداد <code>bind-address</code>، فهذا يعني أن السبب أمر آخر. قد ترغب - في الحالتين – في التعرّف على كيفيّة إعداد اتّصال بعيد أكثر أمانًا، والتي يشرحها المقال <a href="https://academy.hsoub.com/devops/servers/databases/mysql/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%A5%D8%B9%D8%AF%D8%A7%D8%AF-%D9%82%D8%A7%D8%B9%D8%AF%D8%A9-%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-%D8%A8%D8%B9%D9%8A%D8%AF%D8%A9-%D9%84%D8%AA%D8%AD%D8%B3%D9%8A%D9%86-%D8%A3%D8%AF%D8%A7%D8%A1-%D9%85%D9%88%D9%82%D8%B9-%D9%8A%D8%B3%D8%AA%D8%AE%D8%AF%D9%90%D9%85-mysql-r9/" rel="">كيفية إعداد قاعدة بيانات بعيدة لتحسين أداء موقع يستخدِم MySQL</a>.
</p>

<p>
	ترجمة – بتصرّف – للمقال <a href="https://www.digitalocean.com/community/tutorials/how-to-allow-remote-access-to-mysql" rel="external nofollow">How To Allow Remote Access to MySQ</a> لصاحبه Mark Drake.
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
<li>
		المقال التالي: <a href="https://academy.hsoub.com/devops/servers/databases/mysql/%D9%83%D9%8A%D9%81-%D8%AA%D8%B9%D8%A7%D9%84%D8%AC-%D8%A7%D9%86%D9%87%D9%8A%D8%A7%D8%B1-%D8%AE%D8%A7%D8%AF%D9%88%D9%85-mysql-r404/" rel="">كيف تعالج انهيار خادوم MySQL</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">403</guid><pubDate>Sun, 14 Apr 2019 10:10:34 +0000</pubDate></item><item><title>&#x643;&#x64A;&#x641; &#x62A;&#x639;&#x631;&#x636; &#x633;&#x62C;&#x644;&#x627;&#x62A; &#x627;&#x644;&#x623;&#x62E;&#x637;&#x627;&#x621; &#x648;&#x62A;&#x634;&#x62E;&#x635; &#x627;&#x644;&#x627;&#x633;&#x62A;&#x639;&#x644;&#x627;&#x645;&#x627;&#x62A; &#x641;&#x64A; MySQL</title><link>https://academy.hsoub.com/devops/servers/databases/mysql/%D9%83%D9%8A%D9%81-%D8%AA%D8%B9%D8%B1%D8%B6-%D8%B3%D8%AC%D9%84%D8%A7%D8%AA-%D8%A7%D9%84%D8%A3%D8%AE%D8%B7%D8%A7%D8%A1-%D9%88%D8%AA%D8%B4%D8%AE%D8%B5-%D8%A7%D9%84%D8%A7%D8%B3%D8%AA%D8%B9%D9%84%D8%A7%D9%85%D8%A7%D8%AA-%D9%81%D9%8A-mysql-r402/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2019_04/5cb2e331d9bcf_-------mysql.jpg.ef787847102a9663fdd04ed7cbbe2d69.jpg" /></p>

<p>
	يهدف هذا الدليل إلى أن يكون مصدرًا ونقطة بداية لتشخيص واستكشاف مشاكل وإعدادات MySQL للتمهيد لحلها. سنتناول بعضًا من المشاكل التي يتعرّض لها كثيرون من مستخدمي MySQL ونوفّر إرشادات لكيفية تشخيصها وحلها. سيشتمل الدليل كذلك على روابط لمقالات من أكاديميّة حسوب ومن التوثيق الرسمي للاستفادة منها.
</p>

<p>
	فهرس مقالات السلسلة:
</p>

<ul>
<li>
		كيف تعرض سجلّات الأخطاء وتشخّص الاستعلامات في MySQL
	</li>
	<li>
		<a href="https://academy.hsoub.com/devops/servers/databases/mysql/%D9%83%D9%8A%D9%81-%D8%AA%D8%B3%D9%85%D8%AD-%D8%A8%D8%A7%D9%84%D8%A7%D8%AA%D8%B5%D8%A7%D9%84-%D8%B9%D9%86-%D8%A8%D8%B9%D8%AF-%D8%A8%D9%82%D8%A7%D8%B9%D8%AF%D8%A9-%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-mysql-r403/" rel="">كيف تسمح بالاتّصال عن بعد بقاعدة بيانات MySQL</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/devops/servers/databases/mysql/%D9%83%D9%8A%D9%81-%D8%AA%D8%B9%D8%A7%D9%84%D8%AC-%D8%A7%D9%86%D9%87%D9%8A%D8%A7%D8%B1-%D8%AE%D8%A7%D8%AF%D9%88%D9%85-mysql-r404/" rel="">كيف تعالج انهيّار خادوم MySQL</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/devops/servers/databases/mysql/%D9%83%D9%8A%D9%81-%D8%AA%D8%B5%D9%84%D8%AD-%D8%A7%D9%84%D8%AC%D8%AF%D8%A7%D9%88%D9%84-%D8%A7%D9%84%D9%85%D8%B9%D8%B7%D9%88%D8%A8%D8%A9-%D9%81%D9%8A-mysql-r405/" rel="">كيف تصلح الجداول المعطوبة في MySQL</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/devops/servers/databases/mysql/%D9%83%D9%8A%D9%81-%D8%AA%D8%B4%D8%AE%D8%B5-%D8%A3%D8%AE%D8%B7%D8%A7%D8%A1-%D8%A7%D9%84%D9%85%D9%82%D8%A7%D8%A8%D8%B3-sockets-%D9%81%D9%8A-mysql-r406/" rel="">كيف تشخّص أخطاء المقابس Sockets في MySQL</a>
	</li>
</ul>
<p>
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="29159" href="https://academy.hsoub.com/uploads/monthly_2019_04/5cb2e375d2fb0_-------mysql.jpg.c9ad013280bdebe2245f313bfac68d59.jpg" rel=""><img alt="كيف-تعرض-سجلات-الأخطاء-وتشخص-الاستعلامات-في-mysql.jpg" class="ipsImage ipsImage_thumbnailed" data-fileid="29159" data-unique="opqcutvlu" src="https://academy.hsoub.com/uploads/monthly_2019_04/5cb2e37600ec5_-------mysql.thumb.jpg.196d4ae62926a3b9fb073f2404b96386.jpg"></a>
</p>

<p>
	يمكن في كثير من الأحيان التعرّف على السبب وراء بطء، أو انهيار، أو أي سلوك غير متوقّع من قاعدة قاعدة البيانات MySQL بتحليل سجلات الأخطاء. توجد هذه السجلات مبدئيًّا في المسار <code>‎/var/log/mysql/error.log‎</code>، بالنسبة للخواديم التي تعمل بتوزيعة أوبونتو. يعدّ برنامج <code>less</code>، وهو أداة تعمل على سطر الأوامر تتيح قراءة الملفّات دون إمكانيّة تعديلها، الوسيلة الأسهل في كثير من الأحيان، لقراءة سجلات الأخطاء:
</p>

<pre class="ipsCode" id="ips_uid_599_6">
$ sudo less /var/log/mysql/error.log
</pre>

<p>
	يمكن الحصول على معلومات أكثر عن مصدر المشاكل في حال سلوك غير متوقّع من MySQL عبر تنفيذ الأمر أعلاه وتشخيص الخطأ بناءً على محتويات السجلّات.
</p>

<h2 id="-mysql">
	تشخيص استعلامات MySQL
</h2>

<p>
	قد يواجه المستخدمون، فور بدئهم في تنفيذ الاستعلامات Queries، مشاكل بطء في قاعدة بيانات MySQL. يجب عند تنفيذ استعلامات في بعض من أنظمة قواعد البيانات، بما فيها MySQL، إنهاء الاستعلام بفاصلة منقوطة (<code>;</code>) من أجل إتمام الاستعلام؛ كما في المثال التالي :
</p>

<pre class="ipsCode" id="ips_uid_599_8">
SHOW * FROM table_name;
</pre>

<p>
	إن لم تضف فاصلة منقوطة في نهاية الاستعلام، فإن سطر الأوامر سيستمر في الانتقال إلى سطر جديد ما لم تكتب الفاصلة المنقوطة وتضغط بعدها على زر الإدخال <code>Enter</code>. قد يجد بعضٌ من المستخدمين أن استعلاماتهم بطيئة إلى حد بعيد. يعدّ تمكين سجلّ الاستعلامات البطيئة في MySQL ومراجعته. إحدى الطرق الناجعة لمعرفة سبب البطء. لفعل ذلك، افتح الملف <code>mysqld.cnf</code> الذي يُستخدَم لضبط خيارات خادوم MySQL. يوجد هذا الملف عادةً في المسار <code>‎/etc/mysql/mysql.conf.d/‎</code> :
</p>

<pre class="ipsCode" id="ips_uid_599_10">
sudo nano /etc/mysql/mysql.conf.d/mysqld.cnf
</pre>

<p>
	تَنقّل في الملف إلى أن تبلغ الأسطر التالية :
</p>

<pre class="ipsCode" id="ips_uid_599_12">
. . .
#slow_query_log         = 1
#slow_query_log_file    = /var/log/mysql/mysql-slow.log
#long_query_time = 2
#log-queries-not-using-indexes
. . .
</pre>

<p>
	تضبُط التوجيهات المُعلّقة أعلاه (توجد علامة <code>#</code> قبلها) خيّارات الإعداد المبدئيّة لسجلّ الاستعلامات البطيئة. في ما يلي شرحٌ لعمل كلّ منها :
</p>

<ul>
<li>
		<code>slow-query-log</code>: إعطاء القيمة <code>1</code> لهذا التوجيه يفعّل سجلّ الاستعلامات البطيئة.
	</li>
	<li>
		<code>Slow-query-log-file</code>: يعرّف الملفّ الذي سيسجّل فيه MySQL الاستعلامات البطيئة. يشير التوجيه في المثال أعلاه إلى الملف <code>‎/var/log/mysql-slow.log</code>.
	</li>
	<li>
		<code>long_query_time</code> : يؤدي إعطاء القيمة <code>2</code> لهذا التوجيه إلى ضبط MySQL لتسجيل جميع الاستعلامات التي تتجاوز مدة تنفيذها الثانيتين.
	</li>
	<li>
		<code>log_queries_not_using_indexes</code> : يخبر MySQL أن يسجّل أي استعلام لا يستخدم فهارس Indexes ضمن الملف <code>‎/var/log/mysql-slow.log</code>. ليس مفروضًا استخدامُ هذا الإعداد لكي يعمل سجل الاستعلامات البطيئة إلا أنه مفيد جدًّا في التعرّف على الاستعلامات غير الفعّالة.
	</li>
</ul>
<p>
	انزع تعليق الأسطُر بحذف علامة <code>#</code> من أوّلها. سيبدو المقطع أعلاه على النحو التالي بعد نزع التعليقات:
</p>

<pre class="ipsCode" id="ips_uid_599_14">
. . .
slow_query_log = 1
slow_query_log_file = /var/log/mysql-slow.log
long_query_time = 2
log_queries_not_using_indexes
. . .
</pre>

<p>
	<strong>ملحوظة:</strong> إن كنت تسخدم الإصدار 8 وما تلاه من MySQL، فلن يحتوي الملف <code>mysqld.cnf</code> مبدئيًّا على الأسطُر المعلّقة التي تحدّثنا عنها آنفًا، لذا أضف توجيهات الإعداد أسفل الملف على النحو التالي :
</p>

<pre class="ipsCode" id="ips_uid_599_16">
. . .
slow_query_log = 1
slow_query_log_file = /var/log/mysql-slow.log
long_query_time = 2
log_queries_not_using_indexes
</pre>

<p>
	احفظ الملف بعد تمكين سجلّ الاستعلامات البطيئة ثم أغلقه. أعد تشغيل خدمة MySQL كما يلي :
</p>

<pre class="ipsCode" id="ips_uid_599_20">
sudo systemctl restart mysql
</pre>

<p>
	سيمكن بعد هذه الإعدادات العثور على الاستعلامات التي تسبّب مشاكل بطء الخادوم. استخدم الأمر less لعرض الملف كما يلي :
</p>

<pre class="ipsCode" id="ips_uid_599_22">
sudo less /var/log/mysql_slow.log
</pre>

<p>
	الخطوة التالية بعد فرز الاستعلامات البطيئة هي البحث عن طريقة لتحسينها؛ مقال <a href="https://academy.hsoub.com/devops/servers/databases/mysql/%D9%83%D9%8A%D9%81-%D8%AA%D8%AD%D8%B3%D9%91%D9%86-%D8%A7%D9%84%D8%A7%D8%B3%D8%AA%D8%B9%D9%84%D8%A7%D9%85%D8%A7%D8%AA-%D9%88%D8%A7%D9%84%D8%AC%D8%AF%D8%A7%D9%88%D9%84-%D9%81%D9%8A-%D9%82%D8%A7%D8%B9%D8%AF%D8%A9-%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-mysql-r313/" rel="">كيف تحسّن الاستعلامات والجداول في MySQL و MariaDB</a> مفيد لهذا الغرض. علاوة على ذلك؛ يتضمّن MySQL التعليمة <code>EXPLAIN</code> التي توفّر معلومات عن كيفيّة تنفيذ MySQL للاستعلامات. تقدّم <a href="https://dev.mysql.com/doc/refman/5.7/en/using-explain.html" rel="external nofollow">هذه الصفحة</a> من التوثيق الرسمي لـ MySQL أفكارًا حول كيفيّة استخدام EXPLAIN لتسليط الضوء على الاستعلامات غير الفعّالة.
</p>

<p>
	راجع المقال <a href="https://academy.hsoub.com/programming/sql/%D8%A3%D8%B3%D8%A7%D8%B3%D9%8A%D9%91%D8%A7%D8%AA-%D9%84%D8%BA%D8%A9-sql-r585/" rel="">أساسيّات لغة SQL</a> من أجل التعرّف على البنية الأساسيّة لتعليمات MySQL.
</p>

<p>
	ترجمة – بتصرّف – للمقالين <a href="https://www.digitalocean.com/community/tutorials/how-to-access-mysql-error-logs" rel="external nofollow">How to Access MySQL Error Logs</a> و <a href="https://www.digitalocean.com/community/tutorials/how-to-troubleshoot-mysql-queries" rel="external nofollow">How To Troubleshoot MySQL Queries</a> لصاحبهما Mark Drake.
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
<li>
		المقال التالي: <a href="https://academy.hsoub.com/devops/servers/databases/mysql/%D9%83%D9%8A%D9%81-%D8%AA%D8%B3%D9%85%D8%AD-%D8%A8%D8%A7%D9%84%D8%A7%D8%AA%D8%B5%D8%A7%D9%84-%D8%B9%D9%86-%D8%A8%D8%B9%D8%AF-%D8%A8%D9%82%D8%A7%D8%B9%D8%AF%D8%A9-%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-mysql-r403/" rel="">كيف تسمح بالاتّصال عن بعد بقاعدة بيانات MySQL</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">402</guid><pubDate>Sun, 14 Apr 2019 13:02:00 +0000</pubDate></item><item><title>[&#x641;&#x64A;&#x62F;&#x64A;&#x648;] &#x62A;&#x62B;&#x628;&#x64A;&#x62A; &#x648;&#x625;&#x639;&#x62F;&#x627;&#x62F; &#x642;&#x627;&#x639;&#x62F;&#x629; &#x628;&#x64A;&#x627;&#x646;&#x627;&#x62A; MySQL</title><link>https://academy.hsoub.com/devops/servers/databases/mysql/%D9%81%D9%8A%D8%AF%D9%8A%D9%88-%D8%AA%D8%AB%D8%A8%D9%8A%D8%AA-%D9%88%D8%A5%D8%B9%D8%AF%D8%A7%D8%AF-%D9%82%D8%A7%D8%B9%D8%AF%D8%A9-%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-mysql-r399/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2019_03/mysql.png.94e6e25b52d79b71f687b15797317eee.png" /></p>

<p>
	<iframe allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen="" frameborder="0" height="400" width="560" src="https://www.youtube.com/embed/ZD3N4aJzIbg"></iframe>
</p>

<p>
	نشرح طريقة تنصيب وإعداد خادم MySQL على نظام أوبنتو 18.04. مع إعداد كلمة مرور للمستخدم root؛ وإنشاء قاعدة بيانات جديدة ومستخدم جديد لديه الصلاحيات الكاملة عليها.
</p>

<p>
	نوفر توثيقًا كاملًا لجميع تعليمات SQL على موسوعة حسوب:<br><a href="https://wiki.hsoub.com/SQL" ipsnoembed="true" rel="external">https://wiki.hsoub.com/SQL</a>
</p>

<p>
	 
</p>
]]></description><guid isPermaLink="false">399</guid><pubDate>Sat, 16 Mar 2019 06:15:16 +0000</pubDate></item><item><title>&#x627;&#x644;&#x646;&#x633;&#x62E; &#x627;&#x644;&#x645;&#x62A;&#x645;&#x627;&#x62B;&#x644; Master-Slave &#x644;&#x642;&#x648;&#x627;&#x639;&#x62F; &#x628;&#x64A;&#x627;&#x646;&#x627;&#x62A; MySQL &#x639;&#x644;&#x649; &#x646;&#x641;&#x633; &#x627;&#x644;&#x62C;&#x647;&#x627;&#x632;</title><link>https://academy.hsoub.com/devops/servers/databases/mysql/%D8%A7%D9%84%D9%86%D8%B3%D8%AE-%D8%A7%D9%84%D9%85%D8%AA%D9%85%D8%A7%D8%AB%D9%84-master-slave-%D9%84%D9%82%D9%88%D8%A7%D8%B9%D8%AF-%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-mysql-%D8%B9%D9%84%D9%89-%D9%86%D9%81%D8%B3-%D8%A7%D9%84%D8%AC%D9%87%D8%A7%D8%B2-r386/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2018_02/5a8d5c1cb5cb3_22-2(1).png.997cb98a2abbd40d68db876662c47492.png" /></p>

<p>
	MySQL replication هي العمليّة التي يمكن من خلالها نسخ البيانات أوتوماتيكيًا من أحد مخدّمات قاعدة بيانات MySQL “الرئيسي” (master) إلى واحد أو أكثر من مخدّمات قواعد بيانات MySQL “التابع” (slaves). وعادةً ما تستخدم لتوزيع إمكانيّة وصول القراءة read access على مخدّمات متعددة من أجل قابلية التوسع scalability، كما يمكن أن تستخدم أيضًا لأغراض أخرى مثل تجاوز الفشل failover، أو تحليل البيانات على الـ slave من أجل عدم زيادة التحميل على الـ master. كما أنّ الـ master-slave replication هي عمليّة باتجاه واحد (من الـ master إلى slave)، تستخدم قاعدة بيانات الـ master فقط لعمليات الكتابة. بينما يمكن أن توزّع عمليات القراءة على عدّة قواعد بيانات slave. ما الذي يعنيه إذا استخدم master-slave replication كحل للتوسع، ستحتاج لأن تملك على الأقل مصدرين محدّدين للبيانات، واحد لعمليات الكتابة وآخر لعمليات القراءة.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="27119" href="https://academy.hsoub.com/uploads/monthly_2018_02/5a8d5087df271_001(2).jpg.a457df59f50664a5bfe1e2d5ee6e7bd4.jpg" rel=""><img alt="001 (2).jpg" class="ipsImage ipsImage_thumbnailed" data-fileid="27119" data-unique="bim27ppnz" src="https://academy.hsoub.com/uploads/monthly_2018_02/5a8d5087f396d_001(2).thumb.jpg.fbe8f861aad0960ca15f305b99b43e6d.jpg"></a>
</p>

<p>
	يعمل مطوّرو MySQL عادةً على جهاز واحد فقط و ويسعون لأن يكون لديهم كامل بيئة التطوير على ذلك الجهاز. مع منطق عدم الاعتماد على شبكة أو اتصال بالإنترنت. إذا كان هناك حاجة لـ master-slave replication فلأنه على سبيل المثال، يحتاجون إلى اختبار النسخ المتماثل/التكرار replication في بيئة التطوير قبل نشر التغييرات في مكان آخر، عليهم إنشاؤئه على نفس الجهاز. إن الإعداد لمثال MySQL واحد (single MySQL instance) بسيط نوعًا ما، ونحتاج لبذل بعض الجهد الإضافي لإعداد المثال الثاني، وبعدها عملية التكرار master-slave replication.<br>
	للمتابعة في هذه الدرس خطوة بخطوة، اخترت Ubuntu Linux كنظام تشغيل مضيف (host). والأوامر الواردة هي من أجل هذا النظام. إذا أردت إعداد الـ MySQL master-slave replication الخاص بك على نظام تشغيل مختلف، ستكون بحاجة إلى القيام بتعديلات على هذه الأوامر. ومع ذلك ، المبادئ العامة لإعداد الـ MySQL master-slave replication على نفس الجهاز هي نفسها بالنسبة لجميع أنظمة التشغيل.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="27120" href="https://academy.hsoub.com/uploads/monthly_2018_02/5a8d509d6eddc_002(2).jpg.e2913f847eab8bc4a83b640355efed7f.jpg" rel=""><img alt="002 (2).jpg" class="ipsImage ipsImage_thumbnailed" data-fileid="27120" data-unique="4t6132ozy" src="https://academy.hsoub.com/uploads/monthly_2018_02/5a8d509d819d7_002(2).thumb.jpg.d9976c393e555b8fbda88a9abdacac2c.jpg"></a>
</p>

<h2 id="تثبيت-أول-مثالmysql--mysql-instance">
	تثبيت أول مثالMySQL (MySQL instance)
</h2>

<p>
	إذا كان لديك مسبقًا مثال قاعدة بيانات MySQL واحد على جهازك، فيمكنك تجاوز هذه الخطوة.<br>
	هذه أسهل طريقة لتثبيت MySQL على نظام Ubuntu وهي بتشغيل الأوامر التالية في موجّه الطرفية (terminal prompt):
</p>

<pre class="ipsCode" id="ips_uid_3690_7">
sudo apt-get install mysql-server</pre>

<p>
	خلال عملية التثبيت، ستُقاطع لوضع كلمة مرور لمستخدم root لـ MySQL.
</p>

<h2 id="إعداد-mysqld_multi">
	إعداد mysqld_multi
</h2>

<p>
	من أجل إدارة مثالية لـ MuSQL على نفس الجهاز بكفاءة، نحن بحاجة إلى استخدام <code>mysqld_multi</code>. الخطوة الأولى في إعداد <code>mysqld_multi</code> هي إنشاء مجموعتي <code>[mysqld]</code> منفصلتين في الملف الموجود <code>my.cnf</code>. المكان الافتراضي لملف <code>my.cnf</code> في Ubuntu هو <code>/etc/mysql/</code>. لذلك افتح ملف <code>my.cnf</code> بمحرّر نصوصك المفضّل، وسمِّ مجموعة <code>[mysqld]</code> الموجودة إلى <code>[mysqld1]</code>. هذه المجموعة المسمّاة تستخدم لتكوين أول مثال MySQL وستكوّن أيضا كمثال رئيسي. كما هو الحال في MySQL master-slave replication كل مثال يجب أن يكون له <code>server-id</code> فريد خاص به، أضف السطر التالي في مجموعة <code>[mysqld1]</code>:
</p>

<pre class="ipsCode" id="ips_uid_3690_9">
server-id = 1</pre>

<p>
	نظرًا لأننا بحاجة إلى مجموعة <code>[mysqld]</code>منفصلة لمثال MySQL الثاني ، انسخ المجموعة <code>[mysqld1]</code> مع كافة التهيئات الحالية، والصقها في ملف <code>my.cnf</code> نفسه. الآن، أعد تسمية المجموعة المنسوخة إلى <code>[mysqld2]</code>، وقم بإجراء التغييرات التالية في تكوين الـ slave:
</p>

<pre class="ipsCode" id="ips_uid_3690_11">
server-id           = 2
port                = 3307
socket              = /var/run/mysqld/mysqld_slave.sock
pid-file            = /var/run/mysqld/mysqld_slave.pid
datadir             = /var/lib/mysql_slave
log_error           = /var/log/mysql_slave/error_slave.log
relay-log           = /var/log/mysql_slave/relay-bin
relay-log-index     = /var/log/mysql_slave/relay-bin.index
master-info-file    = /var/log/mysql_slave/master.info
relay-log-info-file = /var/log/mysql_slave/relay-log.info
read_only           = 1</pre>

<p>
	لإعداد مثيل MySQL الثاني كـتابع slave ، اضبط <code>server-id</code> إلى 2، والتي يجب أن تكون مختلفة بالنسبة لـ <code>master’s server-id</code>. كلا المثالين سيُشغّلان على نفس الجهاز، اضبط منفذ المثال الثاني إلى قيمة 3307 بحيث يمتلك رقم مختلف عن المنفذ الخاص بالمثال الأول، والذي يكون افتراضيًا 3306. من أجل تفعيل هذا المثال الثاني ليستخدم نفس MySQL binaries، نحتاج <a href="https://dev.mysql.com/doc/refman/5.7/en/server-options.html" rel="external nofollow">لضبط قيم مختلفة</a> للـ <code>socket</code>، <code>pid-file، datadir</code> و <code>log_error</code>.<br>
	نحن أيضًا بحاجة لتفعيل <code>relay-log</code> من أجل استخدام المثال الثاني كتابع (slave) (<a href="https://dev.mysql.com/doc/refman/5.7/en/replication-options-slave.html" rel="external nofollow">المتغيرات</a> <code>relay-log</code>، <code>relay-log-index</code> و <code>relay-log-info-file</code>)، فضلًا عن تعيين <code>master-info-file</code>. أخيرًا، من أجل جعل المثال التابع للقراءة فقط <code>read-only</code>، ضبط المتغير <code>read_only</code> بقيمة 1. يجب أن تكون حذرًا معه فهو لا يمنع التغيرات بشكل كامل على الـ slave. حتى عندما تضبط <code>read_only</code> إلى 1، سيسمح للتحديثات فقط من المستخدمين الذين يملكون امتياز SUPER. أدخل MySQL المتغير الجديد <code>super_read_only</code> لمنع إجراء تغييرات من قبل مستخدمين الـ SUPER. هذا الخيار متوفر مع الإصدار 5.7.8.<br>
	بعيدًا عن مجموعات الـ <code>[mysqld1]</code> و <code>[mysqld2]</code>، نحن بحاجة إلى إضافة مجموعة جديدة <code>[mysqld_multi]</code> إلى ملف <code>my.cnf</code>.
</p>

<pre class="ipsCode" id="ips_uid_3690_13">
[mysqld_multi]
mysqld     = /usr/bin/mysqld_safe
mysqladmin = /usr/bin/mysqladmin
user       = multi_admin
password   = multipass</pre>

<p>
	بمجرد تثبيتنا لمثال MySQL الثاني، والقيام بتشغيلهما، سنمنح الامتيازات المناسبة للمستخدم <code>multi_admin</code> ليكون قادرًا على إيقاف تشغيل أمثلة MySQL.
</p>

<h2 id="أنشئ-مجلدات-جديدة-من-أجل-مثال-mysql-الثاني">
	أنشئ مجلدات جديدة من أجل مثال MySQL الثاني
</h2>

<p>
	في الخطوة السابقة قمنا بإعداد ملف التكوين من أجل مثال MySQL الثاني. في ملف التكوين هذا يتم استخدام مجلدين جديدين. يجب استخدام أوامر لينكس التالية من أجل إنشاء هذه المجلدات مع الامتيازات المناسبة:
</p>

<pre class="ipsCode" id="ips_uid_3690_15">
mkdir -p /var/lib/mysql_slave
chmod --reference /var/lib/mysql /var/lib/mysql_slave
chown --reference /var/lib/mysql /var/lib/mysql_slave
 
mkdir -p /var/log/mysql_slave
chmod --reference /var/log/mysql /var/log/mysql_slave
chown --reference /var/log/mysql /var/log/mysql_slave</pre>

<h2 id="إعدادات-أمنية-إضافية-في-apparmor">
	إعدادات أمنية إضافية في AppArmor
</h2>

<p>
	في بعض بيئات لينكس، هناك حاجة إلى إعدادات أمن <a href="https://wiki.ubuntu.com/AppArmor" rel="external nofollow">AppArmor</a> لتشغيل مثال MySQL الثاني. على الأقل هي مطلوبة في Ubuntu .<br>
	لإعداد AppArmor بشكل صحيح. حرّر ملف <code>/etc/apparmor.d/usr.sbin.mysqld</code> بمحرّر نصوصك المفضّل، وأضف الأسطر التالية:
</p>

<pre class="ipsCode" id="ips_uid_3690_17">
/var/lib/mysql_slave/ r،
/var/lib/mysql_slave/** rwk،
/var/log/mysql_slave/ r،
/var/log/mysql_slave/* rw،
/var/run/mysqld/mysqld_slave.pid rw،
/var/run/mysqld/mysqld_slave.sock w،
/run/mysqld/mysqld_slave.pid rw،
/run/mysqld/mysqld_slave.sock w،</pre>

<p>
	بعد أن تحفظ الملف، أعد تشغيل الجهاز حتى تصبح هذه التغييرات نافذة المفعول.
</p>

<h2 id="تثبيت-مثال-mysql--الثاني">
	تثبيت مثال MySQL الثاني
</h2>

<p>
	يمكن اتباع عدّة نُهج مختلفة لتركيب مثال MySQL الثاني. يستخدم النهج المعروض في هذه الدورة التعليميّة نفس ثنائيات الـ MySQL كما في الأول، مع ملفات بيانات منفصلة ضرورية للتثبيت الثاني. حيث أننا قمنا بالفعل بإعداد ملف التكوين والمجلدات الضرورية والتغييرات الأمنية في الخطوات السابقة،<br>
	الخطوة الأخيرة في التثبيت للمثال الثاني لـ MySQL هي تهيئة دليل بيانات MySQL. نفذ الأمر التالي من أجل تهيئة دليل بيانات MySQL جديد:
</p>

<pre class="ipsCode" id="ips_uid_3690_19">
mysql_install_db --user=mysql --datadir=/var/lib/mysql_slave</pre>

<p>
	بمجرد تهيئة دليل بيانات MySQL، يمكنك بدء كل من مثالي MySQL باستخدام الخدمة <code>mysqld_multi</code>.
</p>

<pre class="ipsCode" id="ips_uid_3690_21">
mysqld_multi start</pre>

<p>
	ضع كلمة سر الـ root لمثال MySQL الثاني باستخدام الـ <code>mysqladmin</code> مع المضيف والمنفذ المناسبين. وضع في اعتبارك ، أنه إذا تَركت المنفذ والمضيف دون تحديد، سيتصل <code>mysqladmin</code> بأول مثال MySQL افتراضيًا.
</p>

<pre class="ipsCode" id="ips_uid_3690_23">
mysqladmin --host=127.0.0.1 --port=3307 -u root password rootpwd</pre>

<p>
	في المثال الذي في الأعلى قم بوضع “rootpwd” ككلمة سر، ولكن يستحسن استخدام كلمة سر أكثر أمنًا.
</p>

<h2 id="تهيئة-إضافية-لـ-mysqld_multi">
	تهيئة إضافية لـ mysqld_multi
</h2>

<p>
	في نهاية قسم " إعداد <code>mysqld_multi</code>، كتبت أننا سنقدم امتيازات مناسبة للمستخدم <code>multi_admin</code> في وقت لاحق، والآن حان الوقت لذلك. نحن بحاجة إلى منح امتيازات هذا المستخدم في كلا المثالين، لذلك دعونا أولًا نقوم بالاتصال بالمثال الأول:
</p>

<pre class="ipsCode" id="ips_uid_3690_25">
mysql --host=127.0.0.1 --port=3306 -uroot -p</pre>

<p>
	عند تسجيلك الدخول، نفّذ الأمرين التاليين:
</p>

<pre class="ipsCode" id="ips_uid_3690_27">
mysql&gt; GRANT SHUTDOWN ON *.* TO 'multi_admin'@'localhost' IDENTIFIED BY 'multipass';
mysql&gt; FLUSH PRIVILEGES;</pre>

<p>
	اخرج من MySQL client، وقم بالاتصال بالمثال الثاني:
</p>

<pre class="ipsCode" id="ips_uid_3690_29">
mysql --host=127.0.0.1 --port=3307 -uroot -p</pre>

<p>
	عند تسجيلك الدخول، نفّذ نفس الأمرين كما في الأعلى:
</p>

<pre class="ipsCode" id="ips_uid_3690_31">
mysql&gt; GRANT SHUTDOWN ON *.* TO 'multi_admin'@'localhost' IDENTIFIED BY 'multipass';
mysql&gt; FLUSH PRIVILEGES;</pre>

<p>
	اخرج من MySQL client.
</p>

<h2 id="بدء-كل-من-مثالي-mysql-أوتوماتيكيًا-عند-الإقلاع">
	بدء كل من مثالي MySQL أوتوماتيكيًا عند الإقلاع
</h2>

<p>
	الخطوة الأخيرة في إعداد <code>mysqld_multi</code> هي التثبيت لسكريبت الإقلاع الأتوماتيكي في الـ <code>init.d</code>.<br>
	لفعل ذلك، أنشئ ملف جديد سمّه <code>mysqld_multi</code> في <code>/etc/init.d</code>، وامنحه الامتيازات المناسبة:
</p>

<pre class="ipsCode" id="ips_uid_3690_33">
cd /etc/init.d
touch mysqld_multi
chmod +x /etc/init.d/mysqld_multi</pre>

<p>
	افتح هذا الملف الجديد بمحرّر نصوصك المفضل، وانسخ السكريبت التالي:
</p>

<pre class="ipsCode" id="ips_uid_3690_35">
#!/bin/sh

### BEGIN INIT INFO
# Provides:      	scriptname
# Required-Start:	$remote_fs $syslog
# Required-Stop: 	$remote_fs $syslog
# Default-Start: 	2 3 4 5
# Default-Stop:  	0 1 6
# Short-Description: Start daemon at boot time
# Description:   	Enable service provided by daemon.
### END INIT INFO
 
bindir=/usr/bin
 
if test -x $bindir/mysqld_multi
then
    mysqld_multi="$bindir/mysqld_multi";
else
    echo "Can't execute $bindir/mysqld_multi";
    exit;
fi
 
case "$1" in
    'start' )
   	 "$mysqld_multi" start $2
   	 ;;
    'stop' )
   	 "$mysqld_multi" stop $2
   	 ;;
    'report' )
   	 "$mysqld_multi" report $2
   	 ;;
    'restart' )
   	 "$mysqld_multi" stop $2
   	 "$mysqld_multi" start $2
   	 ;;
    *)
   	 echo "Usage: $0 {start|stop|report|restart}" &gt;&amp;2
   	 ;;
esac</pre>

<p>
	أضف خدمة <code>mysqld_multi</code> لـ <code>runlevels</code> الافتراضي بالأمر التالي:
</p>

<pre class="ipsCode" id="ips_uid_3690_37">
update-rc.d mysqld_multi defaults</pre>

<p>
	أعد تشغيل جهازك، وتحقق من أن كلا مثالي MySQL قيد التشغيل باستخدام الأمر التالي:
</p>

<pre class="ipsCode" id="ips_uid_3690_39">
mysqld_multi report</pre>

<h2 id="إعداد-setup-master-slave-replication">
	إعداد Setup master-slave replication
</h2>

<p>
	الآن، عندما يكون لدينا مثالي MySQL قيد التشغيل على نفس الجهاز، نقوم بإعداد المثال الأول كـ master، والثاني كـ slave. تم القيام بجزء واحد من التكوين configuration مسبقا في فصل “إعداد mysqld_multi”. التغيير الوحيد المتبقي في الملف <code>my.cnf</code> هو ضبط <code>binary logging</code> على الـ master. لفعل ذلك، حرّر ملف <code>my.cnf</code> مع التغيرات التالية والإضافات في المجموعة <code>[mysqld1]</code>:
</p>

<pre class="ipsCode" id="ips_uid_3690_41">
log_bin                    	= /var/log/mysql/mysql-bin.log
innodb_flush_log_at_trx_commit  = 1
sync_binlog                	= 1
binlog-format              	= ROW</pre>

<p>
	أعد تشغيل مثال MySQL الرئيسي (master MySQL instance) لتأخذ التغيرات مفعولها:
</p>

<pre class="ipsCode" id="ips_uid_3690_43">
mysqld_multi stop 1
mysqld_multi start 1</pre>

<p>
	من أجل اتصال الـ slave بالـ master بامتيازات تكرار replication مناسبة، يجب أن ينشأ المستخدم الجديد في الـ Master. اتصل بمثال maste باستخدام الـ MySQL clien مع المضيف والمنفذ المناسبين:
</p>

<pre class="ipsCode" id="ips_uid_3690_45">
mysql -uroot -p --host=127.0.0.1 --port=3306</pre>

<p>
	أنشئ مستخدم جديد من أجل التكرار replication:
</p>

<pre class="ipsCode" id="ips_uid_3690_47">
mysql&gt; CREATE USER 'replication'@'%' IDENTIFIED BY 'replication';
mysql&gt; GRANT REPLICATION SLAVE ON *.* TO 'replication'@'%';</pre>

<p>
	اخرج من MySQL client.<br>
	نفّذ الأمر التالي من أجل إنشاء ملف نسخ احتياطي (dump) لبيانات الـ master:
</p>

<pre class="ipsCode" id="ips_uid_3690_49">
mysqldump -uroot -p --host=127.0.0.1 --port=3306 --all-databases --master-data=2 &gt; replicationdump.sql</pre>

<p>
	هنا استخدمنا الخيار <code>--master-data=2</code> من أجل الحصول على تعليق يحتوي على عبارة CHANGE MASTER داخل ملف النسخ الاحتياطي، ذاك التعليق يشير الى إحداثيات الـ replication في وقت النسخ الاحتياطي، وسنحتاج هذه الإحداثيات لاحقًا لتحديث معلومات الـ master في مثال الـ slave. وهنا مثال لهذا التعليق:
</p>

<pre class="ipsCode" id="ips_uid_3690_51">
--
-- Position to start replication or point-in-time recovery from
--

-- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000001'، MASTER_LOG_POS=349;</pre>

<p>
	استورد dump الذي أنشأته في الخطوة السابقة ضمن مثال الـ slave.
</p>

<pre class="ipsCode" id="ips_uid_3690_53">
mysql -uroot -p --host=127.0.0.1 --port=3307 &lt; replicationdump.sql</pre>

<p>
	أخيرًا، من أجل اتصال مثال الـ slave بمثال الـ master، يجب تحديث معلومات الـ master في الـ slave مع متغيرات الاتصال المناسبة.<br>
	اتصل بمثال الـ slave باستخدام MySQL clien مع المضيف والمنفذ المناسبين:
</p>

<pre class="ipsCode" id="ips_uid_3690_55">
mysql -uroot -p --host=127.0.0.1 --port=3307</pre>

<p>
	نفّذ الأمر التالي لتحديث معلومات الـ master (خُذ احداثيات التكرار replication من ملف <code>(dump) replicationdump.sql</code>، كما شُرح سابقًا):
</p>

<pre class="ipsCode" id="ips_uid_3690_57">
mysql&gt; CHANGE MASTER TO
	-&gt; MASTER_HOST='127.0.0.1'،
	-&gt; MASTER_USER='replication'،
	-&gt; MASTER_PASSWORD='replication'،
	-&gt; MASTER_LOG_FILE='mysql-bin.000001'،
	-&gt; MASTER_LOG_POS=349;</pre>

<p>
	نفذ الأمر التالي من أجل تشغيل الـ slave:
</p>

<pre class="ipsCode" id="ips_uid_3690_59">
mysql&gt; START SLAVE;</pre>

<p>
	نفذ الأمر التالي للتأكد من أن replication قيد التشغيل:
</p>

<pre class="ipsCode" id="ips_uid_3690_61">
mysql&gt; SHOW SLAVE STATUS \G</pre>

<p>
	تهانينا. تم إعداد MySQL master-slave replication على نفس الجهاز لديك بنجاح.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="27118" href="https://academy.hsoub.com/uploads/monthly_2018_02/5a8d50866952a_003(2).jpg.abd674f180506cd8c40392398b5b3d64.jpg" rel=""><img alt="003 (2).jpg" class="ipsImage ipsImage_thumbnailed" data-fileid="27118" data-unique="0gv4tp2ze" src="https://academy.hsoub.com/uploads/monthly_2018_02/5a8d50867cba7_003(2).thumb.jpg.347fcf5950eb9dd3a8d6309ad1491959.jpg"></a>
</p>

<h2 id="خاتمة">
	خاتمة
</h2>

<p>
	وجود النسخ المتماثل master-slave مهيئًا في بيئة التطوير الخاصة بك مفيد إذا كنت بحاجة لحل للتوسع في بيئة الإنتاج. بهذه الطريقة، سيكون لديك مصادر بيانات منفصلة مُهيئة لعمليات الكتابة والقراءة وبذلك تكون قادرًا على اختبار أن كل شيء يعمل محلياً كما هو متوقع قبل النشر.<br>
	بالإضافة إلى ذلك، قد تحتاج إلى تكوينات أمثلة slave على نفس الجهاز لاختبار موازن الحمل الذي يوزّع عمليات القراءة إلى عدد من الـ slave. في هذه الحالة، يمكنك استخدام هذه الطريقة لإعداد أمثلة أخرى بتكرار كل الخطوات السابقة نفسها.
</p>

<p>
	ترجمة -وبتصرّف- للمقال <a href="https://www.toptal.com/mysql/mysql-master-slave-replication-tutorial" rel="external nofollow">MySQL Master-Slave Replication on the Same Machine</a> لصاحبه Ivan Bojovic
</p>
]]></description><guid isPermaLink="false">386</guid><pubDate>Wed, 21 Feb 2018 11:47:16 +0000</pubDate></item><item><title>&#x62A;&#x62D;&#x633;&#x64A;&#x646; &#x623;&#x62F;&#x627;&#x621; &#x642;&#x648;&#x627;&#x639;&#x62F; &#x628;&#x64A;&#x627;&#x646;&#x627;&#x62A; SQL &#x644;&#x644;&#x645;&#x637;&#x648;&#x631;&#x64A;&#x646;</title><link>https://academy.hsoub.com/devops/servers/databases/mysql/%D8%AA%D8%AD%D8%B3%D9%8A%D9%86-%D8%A3%D8%AF%D8%A7%D8%A1-%D9%82%D9%88%D8%A7%D8%B9%D8%AF-%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-sql-%D9%84%D9%84%D9%85%D8%B7%D9%88%D8%B1%D9%8A%D9%86-r383/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2018_02/5a84349936ddd_15(1).png.eae0d9a0ff09780f6eca35a28749217a.png" /></p>

<p>
	من الممكن أن تكون المعايرة مهمّة صعبة جدًا، وخاصّة عند العمل مع بيانات ضخمة، حيث أنّ أصغر تغيير من الممكن أن يتسبب بتغيرات غير متوقعه ( إيجابية أو سلبية) على الأداء ككل.<br>
	تتم معظم عمليات معايرة SQl database في الشركات المتوسطة والصغيرة من قبل مدير قاعدة البيانات (Database Administrator (DBA، لكن صدقني، يوجد العديد من المطوّرين بحاجة للقيام بعمليات متعلقة بالإدارة، وأكثر من ذلك أنا شاهدت أنّهم يقومون فعليًّا بعمليات الإدارة في كثير من الشركات التي تتطلع للعمل مع المطوّرين، حين يتطلب الوضع ببساطة تقنيات مختلفة لحل المشاكل، والتي يمكن أن تؤدي إلى خلاف بين زملاء العمل.<br>
	عند التعامل مع بيانات ضخمة، فإنّ التغيير الصغير قد يؤدي إلى تغيرات غير متوقعة على الأداء.
</p>

<p>
	وبناء على ذلك، فإنّ هيكلية الشبكة أيضًا لها تأثير، افترض أن فريق الإدارة DBA team مع قواعد البيانات التي يديرونها يتوضع في الطابق العاشر، بينما يتوضع المطوّرين في الطابق الخامس عشر، أو حتى في بناء مختلف تحت هيكلية منفصلة تمامًا، وبالتالي من الصعب العمل المشترك بينهم بمرونة تحت هذه الظروف، سأقوم بإتمام شيئين هامين في هذه المقالة:
</p>

<ul>
<li>
		تزويد المطوّرين بتقنيات معايرة لقواعد بيانات خاصة بالمطوّرين.
	</li>
	<li>
		شرح كيف يمكن لمطوّري ومديري قواعد البيانات العمل معًا بكفاءة.
	</li>
</ul>
<h2 id="تحسين--قاعدة-البيانات-في-codebase">
	تحسين قاعدة البيانات (في Codebase)
</h2>

<h3 id="الفهارس">
	الفهارس
</h3>

<p>
	إذا كنت حديثًا في مجال قواعد البيانات أو حتى تسأل نفسك، “ماهي معايرة SQL”، فيجب أن تعلم أنّ الفهرسة هي طريقة فعّالة لمعايرة قاعدة البيانات database SQL الخاصة بك، والتي غالبًا ما يتم إهمالها خلال عملية التطوير، كمصطلح أولي: الفهرس index هو هيكلة للبيانات تسمح بتسريع عملية استخلاص هذه البيانات من جدول قاعدة البيانات، عن طريق تأمين عمليات بحث عشوائية سريعة، وطريقة فعّالة للوصول إلى السجلات المرتبة، هذا يعني أنّه حالما تقوم بإنشاء فهرس يمكنك القيام بعمليات الاستعلام والترتيب بشكل أسرع.<br>
	تستخدم الفهارس أيضًا لتعريف المفتاح الرئيسي أو فهرس فريد يضمن أنّ أي عمود آخر لن يحتوي نفس القيمة. بالطبع إنّ موضوع الفهرسة متنوع وهام ولا يمكنني إعطاءه حقه في هذا الوصف الموجز.<br>
	إذا كنت حديثًا على موضوع الفهرسة فأنا أفضل أن تستخدم هذا المخطط لهيكلة استعلاماتك.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="27007" href="https://academy.hsoub.com/uploads/monthly_2018_02/b01.png.af0d8be5f483e51bfa6cc4bac0dbaa81.png" rel=""><img alt="b01.png" class="ipsImage ipsImage_thumbnailed" data-fileid="27007" data-unique="lhk97w3ff" src="https://academy.hsoub.com/uploads/monthly_2018_02/b01.thumb.png.d654afe26a048bb2afc33dec2e23a6a0.png"></a>
</p>

<p>
	بشكل أولي، الهدف هو فهرسة أعمدة البحث والترتيب. لاحظ أنه إذا كانت تجري بشكل مستمر عمليات إدخال <code>INSERT</code> أو تعديل <code>UPDATE</code> أو حذف <code>DELETE</code>، فيجب عليك الحذر من القيام بعمليات الفهرسة، حيث يمكن أن يؤدي إلى هبوط في الأداء، إذ أنّه يتطلب تعديل جميع الفهارس بعد هذه العمليات.<br>
	كذلك مديري قواعد البيانات يقومون بحذف الفهارس قبل القيام مثلًا بإدخال أكثر من مليون سجل دفعة واحدة، وذلك لتسريع عملية الإدخال، ثم يقومون بإعادة إنشاء الفهارس بعد انتهاء الإدخال، تذكر على أية حال أن حذف الفهارس يؤثر على كافة الاستعلامات على الجداول، لذلك هذه الطريقة محبذة فقط عند عملية إدخال واحدة ضخمة للبيانات.
</p>

<h3 id="معايرة-أداء-sql-server-خطط-التنفيذ">
	معايرة أداء SQL Server: خطط التنفيذ
</h3>

<p>
	بالمناسبة، أداة خطة التنفيذ في SQL Server مفيدة لإنشاء الفهارس. مهمتها الأساسية تتمثل في الإظهار المرئي لطرق تحصيل البيانات المختارة من قبل منسق استعلام SQL Server. للحصول على خطة التنفيذ (في برنامج الإدارة SQL Server Management Studio)، قم فقط بالنقر على Include Actual Execution Plan" <code>CTRL + M"</code> قبل بدء تشغيل الاستعلام.<br>
	بعدئذ ،سوف يظهر إطار ثالث اسمه “Execution Plan”، حيث يمكن أن تشاهد اكتشاف فهرس مفقود، ولإنشائه قم بالنقر بالزر اليميني على execution plan وقم باختيار Missing Index Details، بكل بساطة.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="27008" href="https://academy.hsoub.com/uploads/monthly_2018_02/b02.png.83b37e0228d104a6a271b43a71987413.png" rel=""><img alt="b02.png" class="ipsImage ipsImage_thumbnailed" data-fileid="27008" data-unique="mkbz590si" src="https://academy.hsoub.com/uploads/monthly_2018_02/b02.thumb.png.6a3e100a413ecb31571136353834ec88.png"></a>
</p>

<h3 id="معايرة-استعلام-sql-عن-طريق-تجنب-حلقات-الشفرة">
	معايرة استعلام SQL عن طريق تجنب حلقات الشفرة
</h3>

<p>
	تخيّل سيناريو يقوم فيه 1000 استعلام بإضافة بيانات على قاعدة بياناتك بشكل تسلسلي، كالتالي:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_9331_7" style="">
<span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">int</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">1000</span><span class="pun">;</span><span class="pln"> i</span><span class="pun">++)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="typ">SqlCommand</span><span class="pln"> cmd </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">SqlCommand</span><span class="pun">(</span><span class="str">"INSERT INTO TBL (A,B,C) VALUES..."</span><span class="pun">);</span><span class="pln">
    cmd</span><span class="pun">.</span><span class="typ">ExecuteNonQuery</span><span class="pun">();</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يجب عليك تجنب مثل هذه الحلقات في شفرتك، وكمثال سنقوم بتحويل باستخدام العبارات الفريدة <code>INSERT</code> <code>UPDATE</code> مع أسطر وقيم عدّة.
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_9331_7" style="">
<code>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)
</code></pre>

<p>
	تأكد من أن عبارة تتجنب تحديث القيم المخزنة إذا كانت تتطابق مع القيمة الموجودة. مثل هذه يمكن أن تحسّن أداء الاستعلام بشكل كبير عن طريق تعديل مئات السجلات بدل الآلاف وكمثال:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_9331_7" style="">
<code>UPDATE TableName
SET A = @VALUE
WHERE
      B = 'YOUR CONDITION'
            AND A &lt;&gt; @VALUE -- VALIDATION
</code></pre>

<h3 id="تجنّب-الاستعلامات-الفرعيّة--المرتبطة-correlated-subqueries">
	تجنّب الاستعلامات الفرعيّة المرتبطة Correlated Subqueries
</h3>

<p>
	الاستعلامات المرتبطة هي الاستعلامات التي تستخدم قيم من الاستعلام الأب، هذه النوع من الاستعلامات ينحو إلى العمل سجل بعد سجل row-by-row، مرة لكل سجل معاد من الاستعلام الخارجي الأب، ولذلك فإنه ينقص أداء استعلام SQl. المطوّرين الحديثين غالبًا ما يبنون استعلاماتهم على هذه الشاكلة لأنها عادة الطريقة الأسهل.<br>
	هنا تجد مثال عن الاستعلامات المرتبطة:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_9331_7" style="">
<code>SELECT c.Name, 
       c.City,
       (SELECT CompanyName FROM Company WHERE ID = c.CompanyID) AS CompanyName 
FROM Customer c
</code></pre>

<p>
	بشكل خاص، المشكلة تكون بأن الاستعلام الداخلي(<code>...SELECT CompanyName</code>) ينفذ لكل سجل مسترجع من الاستعلام الخارجي (<code>...SELECT c.Name</code>)، لكن لماذا العودة إلى مرّة ثم أخرى في كل مرة يعالج فيها سجل من الاستعلام الخارجي؟<br>
	التقنية الافضل لمعايرة الأداء تكون بمعاملة الاستعلام الفرعي كعملية ربط <code>join</code>
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_9331_7" style="">
<code>SELECT c.Name, 
       c.City, 
       co.CompanyName 
FROM Customer c 
	LEFT JOIN Company co
		ON c.CompanyID = co.CompanyID
</code></pre>

<p>
	وبهذه الحالة نقوم بالمرور على جدول <code>Company</code> مرة واحدة ، نربطه بجدول <code>Customer</code>، وعندها يمكننا الحصول على القيم التي نريدها (<code>co.CompanyName</code>) بشكل أفضل.
</p>

<h3 id="الاختيار-باعتدال-select-sparingly">
	الاختيار باعتدال Select Sparingly
</h3>

<p>
	واحدة من أهم نصائح المعايرة هو تجنب استخدام تعليمة <code>SELECT *</code> . وبدلًا من ذلك يجب تحديد الأعمدة التي تحتاجها فقط مره ثانية. هذا الأمر بسيط، لكن هذا الخطأ منتشر، افترض جدولًا بمئات الأعمدة وملايين السجلات فإذا كان تطبيقك يحتاج إلى عدد محدّد من الأعمدة فقط، فلا حاجة لاستجلاب جميع البيانات، لأن ذلك تضييع للمصادر<br>
	كمثال:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_9331_7" style="">
<code>SELECT * FROM Employees
</code></pre>

<p>
	مقابل
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_9331_7" style="">
<code>SELECT FirstName, City, Country FROM Employees
</code></pre>

<p>
	إذا كنت بالفعل تحتاج إلى كل الأعمدة ، قم بتسميتهم ضمن الاستعلام، هذه ليست قاعدة، لكنها طريقة للمعايرة و لتجنب الأخطاء المستقبلية. كمثال إذا كنت تستخدم التعليمة <code>INSERT... ...SELECT</code> وتم تغيير الجدول عن طريق إضافة عمود جديد، عندها ربما تقع في مشكلة إذا كان هذا العمود غير مطلوبًا في الجدول الهدف وكمثال:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_9331_7" style="">
<code>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
</code></pre>

<p>
	ولتجنب هذا الخطأ عليك تسمية كل عمود بشكل مستقل.
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_9331_7" style="">
<code>INSERT INTO Employees (FirstName, City, Country)
SELECT Name, CityName, CountryName
FROM OldEmployees
</code></pre>

<p>
	<strong>ملاحظة:</strong> على أية حال، هنالك بعض الحالات يكون فيها استخدام <code>SELECT</code> مناسبًا، كمثال من أجل الجداول المؤقتة، وهذا يقودنا الى الفقرة التالية.
</p>

<h3 id="استخدام-الجداول-المؤقتة--temporary-tables">
	استخدام الجداول المؤقتة Temporary Tables
</h3>

<p>
	الجداول المؤقتة عادة ما تزيد تعقيد الاستعلام، فإذا كان بالإمكان كتابة شيفرتك بطريقة بسيطة ومباشرة، فأنا أنصحك بتجنب الجداول المؤقتة. لكن إذا كنت تمتلك إجرائية مخزّنة stored procedure مع عمليات تعديل على البيانات لا يمكن إتمامها باستعلام واحد ، يمكنك استخدام الجداول المؤقتة كوسيط لمساعدتك في تحصيل النتائج النهائية.<br>
	عندما تودّ أن تقوم بعملية ضم جدول ضخم وهنالك قيود على الجدول المذكور، يمكنك تحسين أداء قاعدة البيانات عن طريق ترحيل البيانات الى جدول مؤقت، والقيام بعملية ضم ذلك الجدول، حيث ان الجدول المؤقت يحتوي على سجلات أقل من الجدول الأساسي الضخم، ولذلك ستتم عملية الضم بشكل أسرع. القرار ليس واضح بشكل دائم، ولكن هذا المثال سوف ينبهك للحالات التي يمكنك فيها استخدام الجداول المؤقتة.<br>
	تخيّل جدول الزبائن بملايين من السجلات، وعليك أن تقوم بعملية الضم لمنطقة محدّدة، يمكنك القيام بذلك عن طريق استخدام <code>SELECT INTO</code> ،والقيام بعملية الضم مع الجدول المؤقت.
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_9331_7" style="">
<code>SELECT * INTO #Temp FROM Customer WHERE RegionID = 5
SELECT r.RegionName, t.Name FROM Region r JOIN #Temp t ON t.RegionID = r.RegionID
</code></pre>

<p>
	<strong>لاحظ :</strong> مطوري SQl أيضًا يتجنبون استخدام <code>SELECT INTO</code> لإنشاء الجداول المؤقتة، لأن هذا الأمر يؤدي إلى قفل قاعدة بيانات tempdb database مما يمنع باقي المستخدمين من إنشاء جداول مؤقتة ، ولحسن الحظ تم التصحيح في النسخة السابعة وما بعدها. وكحل بديل عن استخدام الجداول المؤقتة يمكن استخدام الاستعلام الفرعي كجدول.
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_9331_7" style="">
<code>SELECT r.RegionName, t.Name FROM Region r 
JOIN (SELECT * FROM Customer WHERE RegionID = 5) AS t 
ON t.RegionID = r.RegionID
</code></pre>

<p>
	لكن انتظر، هنالك مشكلة في الاستعلام الثاني، كما تم شرحه أعلاه، يجب تضمين الأعمدة التي نحتاجها فقط (عدم استخدام <code>* SELECT</code> )، يجب أخذ هذا الأمر بالحسبان
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_9331_7" style="">
<code>SELECT r.RegionName, t.Name FROM Region r 
JOIN (SELECT Name, RegionID FROM Customer WHERE RegionID = 5) AS t 
ON t.RegionID = r.RegionID
</code></pre>

<p>
	كل هذه الطرق ستعيد نفس البيانات، لكن باستخدام الجداول المؤقتة، وكمثال يمكننا انشاء فهرس في جدول مؤقت لتحسين الأداء.<br>
	وأخيرًا، عندما تنهي عملك بالجدول المؤقت، قم بحذفه لتنظيف مصادر tempdb بدل أن تنتظر عملية الحذف الاوتوماتيكي (عندما يتم إنهاء اتصالك مع قاعدة البيانات)
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_9331_7" style="">
<code>DROP TABLE #temp
</code></pre>

<h2 id="هل-يتواجد-السجل-الخاص-بي؟">
	هل يتواجد السجل الخاص بي؟
</h2>

<p>
	تقنية المعايرة هذه الخاصة ب SQl متعلقة باستخدام التعليمة <code>()EXISTS</code> إذا كنت تنوي تفحص فيما إذا كان السجل موجودًا استخدم <code>()EXISTS</code> بدل من <code>()COUNT</code>. حيث أن <code>()COUNT</code> يقوم بفحص كامل الجدول، معتبرًا جميع القيم التي تطابق شروطك، بينما <code>()EXISTS</code> ستوقف الفحص حالما تجد قيمة مطابقة لما تحتاجه. وهذا يفضي إلى أداء أفضل و شفرة أوضح
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_9331_7" style="">
<code>IF (SELECT COUNT(1) FROM EMPLOYEES WHERE FIRSTNAME LIKE '%JOHN%') &gt; 0
 	PRINT 'YES'
</code></pre>

<p>
	مقابل
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_9331_7" style="">
<code>IF EXISTS(SELECT FIRSTNAME FROM EMPLOYEES WHERE FIRSTNAME LIKE '%JOHN%')
    PRINT 'YES'
</code></pre>

<h3 id="معايرة-قاعدة-البيانات-في-المكتب">
	معايرة قاعدة البيانات (في المكتب)
</h3>

<p>
	مديري ومطوري قاعدة البيانات غالبًا ما يتجادلون فيما إذا كانت القضايا التي يواجهونها متعلقة أو غير متعلقة بالبيانات. ومن خبرتي الشخصية أقدم هنا مجموعة من النصائح لكليهما كي يتمكنا من العمل بشكل أكثر فاعلية.
</p>

<p style="text-align: center;">
	<img alt="b03.png" class="ipsImage ipsImage_thumbnailed" data-fileid="27009" data-unique="1q3lv64ct" src="https://academy.hsoub.com/uploads/monthly_2018_02/b03.png.262ae6913df9dd1cd16896686c594b58.png"></p>

<h3 id="للمطوّرين">
	للمطوّرين:
</h3>

<ol>
<li>
		إذا توقف تطبيقك عن العمل فجأة، فقد لايكون الأمر متعلقًا بقاعدة البيانات، كمثال ربما هنالك مشكلة بالشبكة، قم بالتحقق قليلًا قبل أن ترجع السبب إلى مدير قاعدة البيانات.
	</li>
	<li>
		حتى ولو كنت بارعًا في نمذجة بيانات SQl، قم بطلب المساعدة من مدير قاعدة البيانات في المخطط العلائقي relational diagram فلديه الكثير ليقدمه لك.
	</li>
	<li>
		مديري قاعدة البيانات لا يحبون التغيرات السريعة، هذا طبيعي، عليهم تحليل قاعدة البيانات بشكل كامل واكتشاف مدى تأثير أي تغيير من كافة الزوايا. تغيير بسيط في عمود يمكن أن يستغرق اسبوعًا للإنجاز هذا بسبب أن الخطأ قد يعتبر خسارة ضخمة للشركة. كن صبورًا!
	</li>
	<li>
		لا تقم بالطلب من مدير قاعدة بيانات SQL بإجراء تغييرات على البيانات في بيئة العمل وقت التشغيل. إذا كنت تود الوصول الى قاعدة البيانات النشطة، يجب عليك تحمل المسؤولية عن كافة التغيرات.
	</li>
</ol>
<h3 id="لمديري-قاعدة-بيانات-sql">
	لمديري قاعدة بيانات SQl:
</h3>

<ol>
<li>
		إذا كنت لا تحب أن يسألك النّاس بشأن قاعدة البيانات، قم بتزويدهم بلوحة تبيّن الحالة وقت التشغيل. فالمطوّرين عادة لديهم شك بحالة قاعدة البيانات، وهذه اللوحة تساعد في توفير الوقت والجهد للجميع.
	</li>
	<li>
		ساعد المطوّرين في اختبارات ضمان الجودة للبيئة. قم بتسهيل عملية محاكاة عمل المخدّم مع اختبار بسيط على بيانات حقيقية. مما يوفر الوقت بشكل كبير عليك وعليهم.
	</li>
	<li>
		يقضي المطوّرين كل اليوم متعاملين مع أنظمة بمفاهيم عمل تتغير بشكل مستمر. تفهمك لذلك يجعل الأمر أكثر مرونة، ويمكنك من تجاوز بعض القواعد في اللحظات الحرجة.
	</li>
	<li>
		قواعد البيانات تتطور، سيأتي اليوم الذي تحتاج فيه إلى نقل بياناتك الى إصدار جديد، حيث يعتمد المطوّرين على خصائص جديدة في كل إصدار جديد، لذلك خطط و تحسب لعملية النقل بدلًا من أن تقوم برفض هذه التغيرات.
	</li>
</ol>
<p>
	ترجمة -وبتصرّف- للمقال <a href="https://www.toptal.com/sql/sql-database-tuning-for-developers" rel="external nofollow">SQL-Database-Performance-Tuning-for-Developers</a> لصاحبه Rodrigo Koch
</p>

<p>
	حقوق خلفية الصورة البارزة <a href="https://www.vexels.com/download-vector/125857/gradient-clouds-background" rel="external nofollow">Gradient clouds background</a> محفوظة لـ Vexels
</p>
]]></description><guid isPermaLink="false">383</guid><pubDate>Thu, 15 Feb 2018 07:02:00 +0000</pubDate></item><item><title>&#x643;&#x64A;&#x641;&#x64A;&#x629; &#x627;&#x633;&#x62A;&#x64A;&#x631;&#x627;&#x62F; &#x648;&#x62A;&#x635;&#x62F;&#x64A;&#x631; &#x642;&#x648;&#x627;&#x639;&#x62F; &#x628;&#x64A;&#x627;&#x646;&#x627;&#x62A; MySQL &#x623;&#x648; MariaDB</title><link>https://academy.hsoub.com/devops/servers/databases/mysql/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%A7%D8%B3%D8%AA%D9%8A%D8%B1%D8%A7%D8%AF-%D9%88%D8%AA%D8%B5%D8%AF%D9%8A%D8%B1-%D9%82%D9%88%D8%A7%D8%B9%D8%AF-%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-mysql-%D8%A3%D9%88-mariadb-r361/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2017_11/04.png.c99212e10f535f9c2df224af9bfb4bc4.png" /></p>

<p>
	إحدى المهارات الأساسية والمهمة التي عليك أن تتقنها هي القدرة على استيراد وتصدير قواعد البيانات، إذ تستطيع أخذ نسخ احتياطية لقواعد بياناتك وتستعيدها عند الحاجة، أو يمكنك الاستفادة منها لنقل البيانات إلى خادوم جديد أو بيئة تطوير مختلفة.<br>
	إجراء عملية تصدير من قواعد بيانات MySQL و MariaDB هو أمرٌ بسيطٌ، وسنشرحه في هذا الدرس إضافةً إلى شرح طريقة استيراد النسخة الاحتياطية.
</p>

<h2 id="المتطلبات-المسبقة">
	المتطلبات المسبقة
</h2>

<p>
	لتصدير أو استيراد قواعد بيانات MySQL ستحتاج إلى:
</p>

<ul>
<li>
		وصول إلى خادوم لينكس يستعمل قواعد بيانات MySQL أو MariaDB.
	</li>
	<li>
		قاعدة بيانات مع معلومات المستخدم القادر على إجراء عمليات عليها.
	</li>
</ul>
<h2 id="تصدير-قاعدة-البيانات">
	تصدير قاعدة البيانات
</h2>

<p>
	تُستعمَل الأداة <code>mysqldump</code> لتصدير قواعد البيانات إلى ملفات SQL نصية، ويمكن بسهولة نقل تلك الملفات كيفما تشاء.<br>
	ستحتاج إلى معرفة اسم قاعدة البيانات نفسها وإلى اسم المستخدم وكلمة المرور لحسابٍ يملك امتيازاتٍ تسمح –على الأقل– بأذونات القراءة الكاملة على قاعدة البيانات.<br>
	استعمل الأمر الآتي لتصدير قاعدة البيانات:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_2936_7" style="">
<span class="pln">mysqldump </span><span class="pun">-</span><span class="pln">u username </span><span class="pun">-</span><span class="pln">p database_name </span><span class="pun">&gt;</span><span class="pln"> data</span><span class="pun">-</span><span class="kwd">dump</span><span class="pun">.</span><span class="pln">sql</span></pre>

<ul>
<li>
		<code>username</code> هو اسم المستخدم الذي يستطيع الوصول إلى قاعدة البيانات
	</li>
	<li>
		<code>database_name</code> هو اسم قاعدة البيانات التي نريد تصديرها
	</li>
	<li>
		<code>data-dump.sql</code> هو مسار الملف الذي نريد حفظ مخرجات عملية التصدير إليه
	</li>
</ul>
<p>
	لن يعرض الأمر السابق أيّة مخرجات مرئية، لكن يمكنك النظر في محتويات الملف <code>data-dump.sql</code> لتتأكد من وجود ملف SQL سليم فيه باستعمال الأمر:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_2936_7" style="">
<code class="hljs lasso"><span class="pln">head </span><span class="hljs-attribute"><span class="pun">-</span><span class="pln">n</span></span><span class="pln"> </span><span class="hljs-number"><span class="lit">5</span></span><span class="pln"> </span><span class="hljs-built_in"><span class="pln">data</span></span><span class="hljs-attribute"><span class="pun">-</span><span class="kwd">dump</span></span><span class="hljs-built_in"><span class="pun">.</span></span><span class="pln">sql</span></code></pre>

<p>
	يجب أن تبدو المخرجات (التي تظهر أوّل خمسة أسطر من الملف) كما يلي، يجدر بالذكر أنَّ الملف الآتي هو ناتج عملية تصدير قاعدة بيانات باسم <code>database_name</code>:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_2936_7" style="">
<code class="hljs asciidoc"><span class="hljs-header"><span class="pun">--</span><span class="pln"> </span><span class="typ">MySQL</span><span class="pln"> </span><span class="kwd">dump</span><span class="pln"> </span><span class="lit">10.13</span><span class="pln">  </span><span class="typ">Distrib</span><span class="pln"> </span><span class="lit">5.7</span><span class="pun">.</span><span class="lit">16</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">for</span><span class="pln"> </span><span class="typ">Linux</span><span class="pln"> </span><span class="pun">(</span><span class="pln">x86_64</span><span class="pun">)</span><span class="pln">
</span><span class="pun">--</span></span><span class="pln">
</span><span class="hljs-bullet"><span class="pun">--</span><span class="pln"> </span></span><span class="typ">Host</span><span class="pun">:</span><span class="pln"> localhost    </span><span class="typ">Database</span><span class="pun">:</span><span class="pln"> database</span><span class="hljs-emphasis"><span class="pln">_name
</span><span class="pun">--</span><span class="pln"> </span><span class="pun">------------------------------------------------------</span><span class="pln">
</span><span class="pun">--</span><span class="pln"> </span><span class="typ">Server</span><span class="pln"> version       </span><span class="lit">5.7</span><span class="pun">.</span><span class="lit">16</span><span class="pun">-</span><span class="lit">0ubuntu0.16</span><span class="pun">.</span><span class="lit">04.1</span></span></code></pre>

<p>
	إذا حدثت أيّة أخطاء أثناء عملية التصدير، فسيعرضها <code>mysqldump</code> على الشاشة مباشرةً.
</p>

<h2 id="استيراد-قاعدة-البيانات">
	استيراد قاعدة البيانات
</h2>

<p>
	لاستيراد ملف SQL مُصدَّر إلى قاعدة بيانات MySQL أو MariaDB، فعليك أولًا إنشاء قاعدة بيانات جديدة التي ستستضيف البيانات المستوردة.<br>
	سجِّل دخولك إلى عميل قواعد البيانات بحساب المستخدم <code>root</code> أو أي حساب آخر له امتيازات كافية لإنشاء قواعد بيانات جديدة:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_2936_7" style="">
<code class="hljs lasso"><span class="pln">mysql </span><span class="hljs-attribute"><span class="pun">-</span><span class="pln">u</span></span><span class="pln"> root </span><span class="hljs-attribute"><span class="pun">-</span><span class="pln">p</span></span></code></pre>

<p>
	ستنتقل الآن إلى سطر الأوامر الخاص بقواعد MySQL، أنشِئ الآن قاعدة بيانات جديدة وليكن اسمها <code>new_database</code>:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_2936_7" style="">
<code class="hljs sql"><span class="hljs-operator"><span class="hljs-keyword"><span class="pln">CREATE</span></span><span class="pln"> </span><span class="hljs-keyword"><span class="pln">DATABASE</span></span><span class="pln"> new_database</span><span class="pun">;</span></span></code></pre>

<p>
	يجب أن تشاهد الناتج الآتي الذي يدل على نجاح إنشائها:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_2936_7" style="">
<code class="hljs livecodeserver"><span class="typ">Query</span><span class="pln"> OK</span><span class="pun">,</span><span class="pln"> </span><span class="hljs-number"><span class="lit">1</span></span><span class="pln"> row affected </span><span class="pun">(</span><span class="hljs-number"><span class="lit">0.00</span></span><span class="pln"> </span><span class="hljs-built_in"><span class="pln">sec</span></span><span class="pun">)</span></code></pre>

<p>
	اخرج الآن من عميل MySQL بكتابة الأمر <code>exit</code> أو بالضغط على الزرين Ctrl+D، وبعد عودتك إلى سطر الأوامر ستستطيع استيراد الملف باستخدام الأمر الآتي:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_2936_7" style="">
<code class="hljs lasso"><span class="pln">mysql </span><span class="hljs-attribute"><span class="pun">-</span><span class="pln">u</span></span><span class="pln"> username </span><span class="hljs-attribute"><span class="pun">-</span><span class="pln">p</span></span><span class="pln"> new_database </span><span class="hljs-subst"><span class="pun">&lt;</span></span><span class="pln"> </span><span class="hljs-built_in"><span class="pln">data</span></span><span class="hljs-attribute"><span class="pun">-</span><span class="kwd">dump</span></span><span class="hljs-built_in"><span class="pun">.</span></span><span class="pln">sql</span></code></pre>

<ul>
<li>
		<code>username</code> هو اسم المستخدم الذي يستطيع الوصول إلى قاعدة البيانات
	</li>
	<li>
		<code>new_database</code> هو اسم قاعدة البيانات التي نريد استيراد البيانات إليها
	</li>
	<li>
		<code>data-dump.sql</code> هو مسار الملف الذي نريد استيراد محتوياته
	</li>
</ul>
<p>
	لن تظهر أية مخرجات إذا نجح تنفيذ الأمر السابق، لكن إن حدثت أخطاء خلال العملية فسيظهرها الأمر <code>mysql</code> على الشاشة.<br>
	يمكنك التأكد من استيراد قاعدة البيانات بتسجيل الدخول إلى عميل MySQL مجددًا وتفحص البيانات، يمكن فعل ذلك بتحديد قاعدة البيانات الجديدة عبر <code>USE new_database</code> ثم كتابة الأمر <code>SHOW TABLES;‎</code> أو ما شابهه.
</p>

<h2 id="الخلاصة">
	الخلاصة
</h2>

<p>
	أصبحت تعلم كيف تصدِّر قواعد بيانات MySQL إلى ملفات وكيف تستوردها مجددًا.<br>
	هنالك خياراتٌ أخرى متاحةٌ للأمر <code>mysqldump</code> التي تُعدِّل سلوك هذا الأمر عند تصدير قواعد البيانات، والتي يمكنك التعرف عليها في صفحة <a href="http://dev.mysql.com/doc/refman/5.7/en/mysqldump.html" rel="external nofollow">التوثيق الرسمي</a>.<br>
	ترجمة –وبتصرّف– للمقال <a href="https://www.digitalocean.com/community/tutorials/how-to-import-and-export-databases-in-mysql-or-mariadb" rel="external nofollow">How To Import and Export Databases in MySQL or MariaDB</a> لصاحبه Mateusz Papiernik
</p>
]]></description><guid isPermaLink="false">361</guid><pubDate>Sat, 04 Nov 2017 07:01:28 +0000</pubDate></item><item><title>&#x643;&#x64A;&#x641;&#x64A;&#x629; &#x636;&#x628;&#x637; &#x62A;&#x634;&#x641;&#x64A;&#x631; SSL/TLS &#x644;&#x644;&#x627;&#x62A;&#x635;&#x627;&#x644;&#x627;&#x62A; &#x625;&#x644;&#x649; &#x642;&#x648;&#x627;&#x639;&#x62F; &#x628;&#x64A;&#x627;&#x646;&#x627;&#x62A; MySQL &#x639;&#x644;&#x649; &#x62E;&#x627;&#x62F;&#x648;&#x645; &#x623;&#x648;&#x628;&#x646;&#x62A;&#x648; 16.04</title><link>https://academy.hsoub.com/devops/servers/databases/mysql/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%B6%D8%A8%D8%B7-%D8%AA%D8%B4%D9%81%D9%8A%D8%B1-ssltls-%D9%84%D9%84%D8%A7%D8%AA%D8%B5%D8%A7%D9%84%D8%A7%D8%AA-%D8%A5%D9%84%D9%89-%D9%82%D9%88%D8%A7%D8%B9%D8%AF-%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-mysql-%D8%B9%D9%84%D9%89-%D8%AE%D8%A7%D8%AF%D9%88%D9%85-%D8%A3%D9%88%D8%A8%D9%86%D8%AA%D9%88-1604-r341/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2017_08/59a178bcce1b8_main(2).png.adfbd14a0f87e059632acf5e036d9620.png" /></p>

<h2 id="تمهيد">
	تمهيد
</h2>

<p>
	إنَّ MySQL هي أشهر نظام مفتوح المصدر لإدارة قواعد البيانات العلاقية في العالم؛ وحاولت برمجيات إدارة الحزم تقليل الجهد اللازم لتثبيت خادوم MySQL وتشغيله، لكن ما يزال عليك إجراء بعض عمليات الضبط بعد التثبيت. وأنصحك بقضاء بعض الوقت محاولًا زيادة حماية وأمان قواعد بياناتك.
</p>

<p>
	تُضبَط MySQL مبدئيا لقبول الاتصالات المحلية فقط، فلو أردتَ السماح بالاتصالات «البعيدة» فمن المهم أن تكون تلك الاتصالات آمنة؛ وسنشرح في هذا الدرس كيفية السماح بالاتصالات البعيدة إلى خادوم MySQL على أوبنتو 16.04 مع تشفير <abbr title="Secure Socket Layer | طبقة المنافذ الآمنة">SSL</abbr>/<abbr title="Transport Layer Security | بروتوكول أمن طبقة النقل">TLS</abbr>.
</p>

<h2 id="المتطلبات-المسبقة">
	المتطلبات المسبقة
</h2>

<p>
	إذا أردتَ المتابعة مع هذا الدرس، فستحتاج إلى خادومَي أوبونتو 16.04، إذ سنستخدم أحدها لاستضافة خادوم MySQL وسيلعب الآخر دور العميل. عليك أيضًا إنشاء مستخدم ليس جذرًا لكنه يمتلك امتيازات الجذر عبر الأمر <code>sudo</code>، راجع درس ا<a href="https://academy.hsoub.com/devops/servers/%D8%A7%D9%84%D8%A5%D8%B9%D8%AF%D8%A7%D8%AF-%D8%A7%D9%84%D8%A7%D8%A8%D8%AA%D8%AF%D8%A7%D8%A6%D9%8A-%D9%84%D8%AE%D8%A7%D8%AF%D9%88%D9%85-%D8%A3%D9%88%D8%A8%D9%86%D8%AA%D9%88-1404-r4/" rel="">لإعداد الابتدائي لخادوم أوبنتو 14.04</a> للمزيد من المعلومات حول الضبط المبدئي لخادومك.
</p>

<p>
	يجب أن تثبّت على الجهاز الأول خادوم MySQL وتضبطه؛ يمكنك العودة إلى درس<a href="https://academy.hsoub.com/devops/servers/databases/%D8%AA%D8%AB%D8%A8%D9%8A%D8%AA-%D9%88%D8%A5%D8%B9%D8%AF%D8%A7%D8%AF-%D9%86%D8%B8%D8%A7%D9%85%D9%8A-%D8%A5%D8%AF%D8%A7%D8%B1%D8%A9-%D9%82%D9%88%D8%A7%D8%B9%D8%AF-%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-mysql-%D9%88postgresql-%D8%B9%D9%84%D9%89-%D8%A3%D9%88%D8%A8%D9%86%D8%AA%D9%88-r194/" rel="">تثبيت وإعداد نظامي إدارة قواعد البياناتMySQL وPostgreSQL على أوبنتو</a> لمزيدٍ من المعلومات حول تثبيت وضبط هذه البرمجية.<br>
	أما على الجهاز الثاني، فعليك تثبيت حزمة عميل MySQL، إذ تستطيع استخدام الأمر <code>apt</code> لتحديث فهرس الحزم ثم تثبيت البرمجيات الضرورية وذلك بتنفيذ الأمرين الآتيين:
</p>

<pre class="ipsCode" id="ips_uid_6311_10">
sudo apt-get update
sudo apt-get install mysql-client</pre>

<p>
	يُفتَرَض أن يعمل خادومك وعمليك عملًا سليمًا.
</p>

<h2 id="التحقق-من-حالة-تشفير-ssltls-الراهنة-على-خادوم-mysql">
	التحقق من حالة تشفير <abbr title="Secure Socket Layer | طبقة المنافذ الآمنة">SSL</abbr>/<abbr title="Transport Layer Security | بروتوكول أمن طبقة النقل">TLS</abbr> الراهنة على خادوم MySQL
</h2>

<p>
	علينا قبل البدء أن نتحقق من الحالة الراهنة لتشفير <abbr title="Secure Socket Layer | طبقة المنافذ الآمنة">SSL</abbr>/<abbr title="Transport Layer Security | بروتوكول أمن طبقة النقل">TLS</abbr> على خادومنا.<br>
	سجِّل دخولك إلى خادومك MySQL عبر المستخدم <code>root</code> التابع لقواعد MySQL. سنستخدم في الأمر الآتي الخيار <code>‎-h</code> لتحديد عنوان IP للجهاز المحلي لكي يتصل العميل باستخدام بروتوكول TCP بدلًا من استخدام ملف socket محلي؛ وهذا سيُمكننا من التحقق من حالة تشفير <abbr title="Secure Socket Layer | طبقة المنافذ الآمنة">SSL</abbr> لاتصالات TCP:
</p>

<pre class="ipsCode" id="ips_uid_6311_8">
mysql -u root -p -h 127.0.0.1</pre>

<p>
	ستُسأل عن كلمة مرور مستخدم <code>root</code> التي اخترتها أثناء عملية تثبيت خادوم MySQL؛ وبعدئذٍ ستنتقل إلى جلسة MySQL تفاعلية.
</p>

<p>
	يمكننا إظهار حالة متغيرات <abbr title="Secure Socket Layer | طبقة المنافذ الآمنة">SSL</abbr>/<abbr title="Transport Layer Security | بروتوكول أمن طبقة النقل">TLS</abbr> عبر كتابة التعليمة الآتية:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_6311_12" style="">
<span class="pln">SHOW VARIABLES LIKE </span><span class="str">'%<abbr title="Secure Socket Layer | طبقة المنافذ الآمنة">ssl</abbr>%'</span><span class="pun">;</span></pre>

<p>
	الناتج:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_6311_14" style="">
<span class="pun">+---------------+----------+</span><span class="pln">
</span><span class="pun">|</span><span class="pln"> </span><span class="typ">Variable_name</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="typ">Value</span><span class="pln">    </span><span class="pun">|</span><span class="pln">
</span><span class="pun">+---------------+----------+</span><span class="pln">
</span><span class="pun">|</span><span class="pln"> have_openssl  </span><span class="pun">|</span><span class="pln"> DISABLED </span><span class="pun">|</span><span class="pln">
</span><span class="pun">|</span><span class="pln"> have_ssl      </span><span class="pun">|</span><span class="pln"> DISABLED </span><span class="pun">|</span><span class="pln">
</span><span class="pun">|</span><span class="pln"> ssl_ca        </span><span class="pun">|</span><span class="pln">          </span><span class="pun">|</span><span class="pln">
</span><span class="pun">|</span><span class="pln"> ssl_capath    </span><span class="pun">|</span><span class="pln">          </span><span class="pun">|</span><span class="pln">
</span><span class="pun">|</span><span class="pln"> ssl_cert      </span><span class="pun">|</span><span class="pln">          </span><span class="pun">|</span><span class="pln">
</span><span class="pun">|</span><span class="pln"> ssl_cipher    </span><span class="pun">|</span><span class="pln">          </span><span class="pun">|</span><span class="pln">
</span><span class="pun">|</span><span class="pln"> ssl_crl       </span><span class="pun">|</span><span class="pln">          </span><span class="pun">|</span><span class="pln">
</span><span class="pun">|</span><span class="pln"> ssl_crlpath   </span><span class="pun">|</span><span class="pln">          </span><span class="pun">|</span><span class="pln">
</span><span class="pun">|</span><span class="pln"> ssl_key       </span><span class="pun">|</span><span class="pln">          </span><span class="pun">|</span><span class="pln">
</span><span class="pun">+---------------+----------+</span><span class="pln">
</span><span class="lit">9</span><span class="pln"> rows </span><span class="kwd">in</span><span class="pln"> </span><span class="kwd">set</span><span class="pln"> </span><span class="pun">(</span><span class="lit">0.01</span><span class="pln"> sec</span><span class="pun">)</span></pre>

<p>
	لاحظ أنَّ قيمة المتغيرين <code>have_openssl</code> و <code>have_ssl</code> تساوي <code>DISABLED</code>، وهذا يعني أنَّ دعم تشفير <abbr title="Secure Socket Layer | طبقة المنافذ الآمنة">SSL</abbr> مبنيٌ داخل الخادوم لكنه ليس مفعلًا بعد.<br>
	لنتحقق من حالة الاتصال الحالي للتأكد من النتائج السابقة، وذلك بإدخال:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_6311_16" style="">
<span class="pln">\s</span></pre>

<p>
	الناتج:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_6311_18" style="">
<span class="pun">--------------</span><span class="pln">
mysql  </span><span class="typ">Ver</span><span class="pln"> </span><span class="lit">14.14</span><span class="pln"> </span><span class="typ">Distrib</span><span class="pln"> </span><span class="lit">5.7</span><span class="pun">.</span><span class="lit">17</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">for</span><span class="pln"> </span><span class="typ">Linux</span><span class="pln"> </span><span class="pun">(</span><span class="pln">x86_64</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">using</span><span class="pln">  </span><span class="typ">EditLine</span><span class="pln"> wrapper

</span><span class="typ">Connection</span><span class="pln"> id</span><span class="pun">:</span><span class="pln">      </span><span class="lit">30</span><span class="pln">
</span><span class="typ">Current</span><span class="pln"> database</span><span class="pun">:</span><span class="pln">   
</span><span class="typ">Current</span><span class="pln"> user</span><span class="pun">:</span><span class="pln">       root@localhost
<abbr title="Secure Socket Layer | طبقة المنافذ الآمنة">SSL</abbr></span><span class="pun">:</span><span class="pln">         </span><span class="typ">Not</span><span class="pln"> </span><span class="kwd">in</span><span class="pln"> </span><span class="kwd">use</span><span class="pln">
</span><span class="typ">Current</span><span class="pln"> pager</span><span class="pun">:</span><span class="pln">      stdout
</span><span class="typ">Using</span><span class="pln"> outfile</span><span class="pun">:</span><span class="pln">      </span><span class="str">''</span><span class="pln">
</span><span class="typ">Using</span><span class="pln"> delimiter</span><span class="pun">:</span><span class="pln">    </span><span class="pun">;</span><span class="pln">
</span><span class="typ">Server</span><span class="pln"> version</span><span class="pun">:</span><span class="pln">     </span><span class="lit">5.7</span><span class="pun">.</span><span class="lit">17</span><span class="pun">-</span><span class="lit">0ubuntu0.16</span><span class="pun">.</span><span class="lit">04.1</span><span class="pln"> </span><span class="pun">(</span><span class="typ">Ubuntu</span><span class="pun">)</span><span class="pln">
</span><span class="typ">Protocol</span><span class="pln"> version</span><span class="pun">:</span><span class="pln">   </span><span class="lit">10</span><span class="pln">
</span><span class="typ">Connection</span><span class="pun">:</span><span class="pln">      </span><span class="lit">127.0</span><span class="pun">.</span><span class="lit">0.1</span><span class="pln"> via TCP</span><span class="pun">/</span><span class="pln">IP
</span><span class="typ">Server</span><span class="pln"> characterset</span><span class="pun">:</span><span class="pln">    latin1
</span><span class="typ">Db</span><span class="pln">     characterset</span><span class="pun">:</span><span class="pln">    latin1
</span><span class="typ">Client</span><span class="pln"> characterset</span><span class="pun">:</span><span class="pln">    utf8
</span><span class="typ">Conn</span><span class="pun">.</span><span class="pln">  characterset</span><span class="pun">:</span><span class="pln">    utf8
TCP port</span><span class="pun">:</span><span class="pln">       </span><span class="lit">3306</span><span class="pln">
</span><span class="typ">Uptime</span><span class="pun">:</span><span class="pln">         </span><span class="lit">3</span><span class="pln"> hours </span><span class="lit">38</span><span class="pln"> min </span><span class="lit">44</span><span class="pln"> sec

</span><span class="typ">Threads</span><span class="pun">:</span><span class="pln"> </span><span class="lit">1</span><span class="pln">  </span><span class="typ">Questions</span><span class="pun">:</span><span class="pln"> </span><span class="lit">70</span><span class="pln">  </span><span class="typ">Slow</span><span class="pln"> queries</span><span class="pun">:</span><span class="pln"> </span><span class="lit">0</span><span class="pln">  </span><span class="typ">Opens</span><span class="pun">:</span><span class="pln"> </span><span class="lit">121</span><span class="pln">  </span><span class="typ">Flush</span><span class="pln"> tables</span><span class="pun">:</span><span class="pln"> </span><span class="lit">1</span><span class="pln">  </span><span class="typ">Open</span><span class="pln"> tables</span><span class="pun">:</span><span class="pln"> </span><span class="lit">40</span><span class="pln">  </span><span class="typ">Queries</span><span class="pln"> per second avg</span><span class="pun">:</span><span class="pln"> </span><span class="lit">0.005</span><span class="pln">
</span><span class="pun">--------------</span></pre>

<p>
	يمكننا أن نلاحظ من الناتج السابق أنَّ الاتصال غير مشفر عبر <abbr title="Secure Socket Layer | طبقة المنافذ الآمنة">SSL</abbr>، حتى لو كنّا قد اتصلنا عبر بروتوكول TCP.
</p>

<p>
	أغلق جلسة MySQL عندما تنتهي:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_6311_20" style="">
<span class="kwd">exit</span></pre>

<p>
	يمكننا الآن البدء بضبط MySQL لتستعمل تشفير <abbr title="Secure Socket Layer | طبقة المنافذ الآمنة">SSL</abbr> للاتصالات القادمة إليها.
</p>

<h2 id="توليد-شهادات-ومفاتيح-ssltls">
	توليد شهادات ومفاتيح <abbr title="Secure Socket Layer | طبقة المنافذ الآمنة">SSL</abbr>/<abbr title="Transport Layer Security | بروتوكول أمن طبقة النقل">TLS</abbr>
</h2>

<p>
	لتفعيل اتصالات مشفرة عبر <abbr title="Secure Socket Layer | طبقة المنافذ الآمنة">SSL</abbr> إلى MySQL، فعلينا أولًا توليد الشهادات والمفاتيح المناسبة.
</p>

<p>
	هنالك أداةٌ باسم <code>mysql_ssl_rsa_setup</code> متوافرة مع MySQL 5.7 وما بعدها مهمتها تبسيط هذه العملية؛ وهنالك إصدار MySQL متوافق معها متوافر في أوبنتو 16.04، لذا سنستخدم هذا الأمر لتوليد الملفات اللازمة.
</p>

<p>
	ستُنشَأ الملفات في مجلد ملفات MySQL الموجود في المسار <code>‎/var/lib/mysql</code>؛ وعلينا السماح لعملية MySQL (أي MySQL process) بقراءة الملفات المولّدة، لذا سنُمرِّر القيمة <code>mysql</code> اسمًا للمستخدم الذي سيملك الملفات المولّدة:
</p>

<pre class="ipsCode" id="ips_uid_6311_22">
sudo mysql_ssl_rsa_setup –uid=mysql</pre>

<p>
	سيكون ناتج عملية التوليد مشابهًا لما يلي:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_6311_24" style="">
<span class="typ">Generating</span><span class="pln"> a </span><span class="lit">2048</span><span class="pln"> bit RSA </span><span class="kwd">private</span><span class="pln"> key
</span><span class="pun">...................................+++</span><span class="pln">
</span><span class="pun">.....+++</span><span class="pln">
writing </span><span class="kwd">new</span><span class="pln"> </span><span class="kwd">private</span><span class="pln"> key to </span><span class="str">'ca-key.pem'</span><span class="pln">
</span><span class="pun">-----</span><span class="pln">
</span><span class="typ">Generating</span><span class="pln"> a </span><span class="lit">2048</span><span class="pln"> bit RSA </span><span class="kwd">private</span><span class="pln"> key
</span><span class="pun">......+++</span><span class="pln">
</span><span class="pun">.................................+++</span><span class="pln">
writing </span><span class="kwd">new</span><span class="pln"> </span><span class="kwd">private</span><span class="pln"> key to </span><span class="str">'server-key.pem'</span><span class="pln">
</span><span class="pun">-----</span><span class="pln">
</span><span class="typ">Generating</span><span class="pln"> a </span><span class="lit">2048</span><span class="pln"> bit RSA </span><span class="kwd">private</span><span class="pln"> key
</span><span class="pun">......................................................+++</span><span class="pln">
</span><span class="pun">.................................................................................+++</span><span class="pln">
writing </span><span class="kwd">new</span><span class="pln"> </span><span class="kwd">private</span><span class="pln"> key to </span><span class="str">'client-key.pem'</span><span class="pln">
</span><span class="pun">-----</span></pre>

<p>
	تحقق من إنشاء الملفات الذي جرت عملية توليدها بالأمر <a href="https://academy.hsoub.com/devops/linux/%D9%83%D9%8A%D9%81-%D8%AA%D8%B3%D8%AA%D8%AE%D8%AF%D9%90%D9%85-%D8%A3%D9%85%D8%B1%D9%8E%D9%8A-find-%D9%88-locate-%D9%84%D9%84%D8%A8%D8%AD%D8%AB-%D8%B9%D9%86-%D8%A7%D9%84%D9%85%D9%84%D9%81%D9%91%D8%A7%D8%AA-%D8%B9%D9%84%D9%89-linux-r43/" rel=""><code>find</code></a>:
</p>

<pre class="ipsCode" id="ips_uid_6311_26">
sudo find /var/lib/mysql -name '*.pem' -ls</pre>

<p>
	الناتج:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_6311_28" style="">
<span class="pln">   </span><span class="lit">256740</span><span class="pln">      </span><span class="lit">4</span><span class="pln"> </span><span class="pun">-</span><span class="pln">rw</span><span class="pun">-</span><span class="pln">r</span><span class="pun">--</span><span class="pln">r</span><span class="pun">--</span><span class="pln">   </span><span class="lit">1</span><span class="pln"> mysql    mysql        </span><span class="lit">1078</span><span class="pln"> </span><span class="typ">Mar</span><span class="pln"> </span><span class="lit">17</span><span class="pln"> </span><span class="lit">17</span><span class="pun">:</span><span class="lit">24</span><span class="pln"> </span><span class="pun">/</span><span class="kwd">var</span><span class="pun">/</span><span class="pln">lib</span><span class="pun">/</span><span class="pln">mysql</span><span class="pun">/</span><span class="pln">server</span><span class="pun">-</span><span class="pln">cert</span><span class="pun">.</span><span class="pln">pem
   </span><span class="lit">256735</span><span class="pln">      </span><span class="lit">4</span><span class="pln"> </span><span class="pun">-</span><span class="pln">rw</span><span class="pun">-------</span><span class="pln">   </span><span class="lit">1</span><span class="pln"> mysql    mysql        </span><span class="lit">1675</span><span class="pln"> </span><span class="typ">Mar</span><span class="pln"> </span><span class="lit">17</span><span class="pln"> </span><span class="lit">17</span><span class="pun">:</span><span class="lit">24</span><span class="pln"> </span><span class="pun">/</span><span class="kwd">var</span><span class="pun">/</span><span class="pln">lib</span><span class="pun">/</span><span class="pln">mysqlsql</span><span class="pun">/</span><span class="pln">ca</span><span class="pun">-</span><span class="pln">key</span><span class="pun">.</span><span class="pln">pem</span><span class="pun">&lt;^&gt;</span><span class="pln">
   </span><span class="lit">256739</span><span class="pln">      </span><span class="lit">4</span><span class="pln"> </span><span class="pun">-</span><span class="pln">rw</span><span class="pun">-</span><span class="pln">r</span><span class="pun">--</span><span class="pln">r</span><span class="pun">--</span><span class="pln">   </span><span class="lit">1</span><span class="pln"> mysql    mysql         </span><span class="lit">451</span><span class="pln"> </span><span class="typ">Mar</span><span class="pln"> </span><span class="lit">17</span><span class="pln"> </span><span class="lit">17</span><span class="pun">:</span><span class="lit">24</span><span class="pln"> </span><span class="pun">/</span><span class="kwd">var</span><span class="pun">/</span><span class="pln">lib</span><span class="pun">/</span><span class="pln">mysqlsql</span><span class="pun">/</span><span class="pln">public_key</span><span class="pun">.</span><span class="pln">pem</span><span class="pun">&lt;^&gt;</span><span class="pln">
   </span><span class="lit">256741</span><span class="pln">      </span><span class="lit">4</span><span class="pln"> </span><span class="pun">-</span><span class="pln">rw</span><span class="pun">-------</span><span class="pln">   </span><span class="lit">1</span><span class="pln"> mysql    mysql        </span><span class="lit">1679</span><span class="pln"> </span><span class="typ">Mar</span><span class="pln"> </span><span class="lit">17</span><span class="pln"> </span><span class="lit">17</span><span class="pun">:</span><span class="lit">24</span><span class="pln"> </span><span class="pun">/</span><span class="kwd">var</span><span class="pun">/</span><span class="pln">lib</span><span class="pun">/</span><span class="pln">mysqlsql</span><span class="pun">/</span><span class="pln">client</span><span class="pun">-</span><span class="pln">key</span><span class="pun">.</span><span class="pln">pem</span><span class="pun">&lt;^&gt;</span><span class="pln">
   </span><span class="lit">256737</span><span class="pln">      </span><span class="lit">4</span><span class="pln"> </span><span class="pun">-</span><span class="pln">rw</span><span class="pun">-</span><span class="pln">r</span><span class="pun">--</span><span class="pln">r</span><span class="pun">--</span><span class="pln">   </span><span class="lit">1</span><span class="pln"> mysql    mysql        </span><span class="lit">1074</span><span class="pln"> </span><span class="typ">Mar</span><span class="pln"> </span><span class="lit">17</span><span class="pln"> </span><span class="lit">17</span><span class="pun">:</span><span class="lit">24</span><span class="pln"> </span><span class="pun">/</span><span class="kwd">var</span><span class="pun">/</span><span class="pln">lib</span><span class="pun">/</span><span class="pln">mysqlsql</span><span class="pun">/</span><span class="pln">ca</span><span class="pun">.</span><span class="pln">pem</span><span class="pun">&lt;^&gt;</span><span class="pln">
   </span><span class="lit">256743</span><span class="pln">      </span><span class="lit">4</span><span class="pln"> </span><span class="pun">-</span><span class="pln">rw</span><span class="pun">-</span><span class="pln">r</span><span class="pun">--</span><span class="pln">r</span><span class="pun">--</span><span class="pln">   </span><span class="lit">1</span><span class="pln"> mysql    mysql        </span><span class="lit">1078</span><span class="pln"> </span><span class="typ">Mar</span><span class="pln"> </span><span class="lit">17</span><span class="pln"> </span><span class="lit">17</span><span class="pun">:</span><span class="lit">24</span><span class="pln"> </span><span class="pun">/</span><span class="kwd">var</span><span class="pun">/</span><span class="pln">lib</span><span class="pun">/</span><span class="pln">mysqlsql</span><span class="pun">/</span><span class="pln">client</span><span class="pun">-</span><span class="pln">cert</span><span class="pun">.</span><span class="pln">pem</span><span class="pun">&lt;^&gt;</span><span class="pln">
   </span><span class="lit">256736</span><span class="pln">      </span><span class="lit">4</span><span class="pln"> </span><span class="pun">-</span><span class="pln">rw</span><span class="pun">-------</span><span class="pln">   </span><span class="lit">1</span><span class="pln"> mysql    mysql        </span><span class="lit">1675</span><span class="pln"> </span><span class="typ">Mar</span><span class="pln"> </span><span class="lit">17</span><span class="pln"> </span><span class="lit">17</span><span class="pun">:</span><span class="lit">24</span><span class="pln"> </span><span class="pun">/</span><span class="kwd">var</span><span class="pun">/</span><span class="pln">lib</span><span class="pun">/</span><span class="pln">mysqlsql</span><span class="pun">/</span><span class="pln">private_key</span><span class="pun">.</span><span class="pln">pem</span><span class="pun">&lt;^&gt;</span><span class="pln">
   </span><span class="lit">256738</span><span class="pln">      </span><span class="lit">4</span><span class="pln"> </span><span class="pun">-</span><span class="pln">rw</span><span class="pun">-------</span><span class="pln">   </span><span class="lit">1</span><span class="pln"> mysql    mysql        </span><span class="lit">1675</span><span class="pln"> </span><span class="typ">Mar</span><span class="pln"> </span><span class="lit">17</span><span class="pln"> </span><span class="lit">17</span><span class="pun">:</span><span class="lit">24</span><span class="pln"> </span><span class="pun">/</span><span class="kwd">var</span><span class="pun">/</span><span class="pln">lib</span><span class="pun">/</span><span class="pln">mysqlsql</span><span class="pun">/</span><span class="pln">server</span><span class="pun">-</span><span class="pln">key</span><span class="pun">.</span><span class="pln">pem</span><span class="pun">&lt;^&gt;</span></pre>

<p>
	آخر عمود من الناتج السابق يُظهِر أسماء الملفات المولّدة، أما العمود الرابع والخامس فيؤكدان أنَّ المستخدم المالك والمجموعة المالكة هو <code>mysql</code>.
</p>

<p>
	تُمثِّل هذه الملفات مفاتيح وشهادات لسلطة الشهادات Certificate authority (للملفات التي تبدأ بالسابقة «ca»)، ولعملية خادوم MySQL (للملفات التي تبدأ بالسابقة «server»)، ولعملاء MySQL (للملفات التي تبدأ بالسابقة «client»). إضافةً إلى ما سبق، هنالك الملفان <code>private_key.pem</code> و <code>public_key.pem</code> اللذان تستعملهما MySQL لنقل كلمة المرور بأمان دون استخدام <abbr title="Secure Socket Layer | طبقة المنافذ الآمنة">SSL</abbr>.
</p>

<h2 id="تفعيل-اتصالات-ssl-الآمنة-على-خادوم-mysql">
	تفعيل اتصالات <abbr title="Secure Socket Layer | طبقة المنافذ الآمنة">SSL</abbr> الآمنة على خادوم MySQL
</h2>

<p>
	ستبحث الإصدارات الحديثة من MySQL عن ملفات الشهادات الملائمة ضمن مجلد بيانات MySQL عندما يبدأ الخادوم. ولهذا السبب، لن نحتاج إلى تعديل ضبط MySQL لتفعيل تشفير <abbr title="Secure Socket Layer | طبقة المنافذ الآمنة">SSL</abbr>.
</p>

<p>
	كل ما علينا فعله هو إعادة تشغيل خدمة MySQL:
</p>

<pre class="ipsCode" id="ips_uid_6311_30">
sudo systemctl restart mysql</pre>

<p>
	بعد إعادة التشغيل، افتح اتصالًا إلى خادوم MySQL بالأمر الذي ذكرناه في بداية هذا الدرس؛ وسيحاول عميل MySQL الاتصال عبر تشفير <abbr title="Secure Socket Layer | طبقة المنافذ الآمنة">SSL</abbr> إن كان مدعومًا من الخادوم:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_6311_32" style="">
<span class="pln">mysql </span><span class="pun">-</span><span class="pln">u root </span><span class="pun">-</span><span class="pln">p </span><span class="pun">-</span><span class="pln">h </span><span class="lit">127.0</span><span class="pun">.</span><span class="lit">0.1</span></pre>

<p>
	لننظر مرةً أخرى إلى المعلومات التي طلبناها أوّل مرة، ولنلاحظ القيم المرتبطة بالمتغيرات المتعلقة بتشفير <abbr title="Secure Socket Layer | طبقة المنافذ الآمنة">SSL</abbr>:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_6311_34" style="">
<span class="pln">SHOW VARIABLES LIKE </span><span class="str">'%<abbr title="Secure Socket Layer | طبقة المنافذ الآمنة">ssl</abbr>%'</span><span class="pun">;</span></pre>

<p>
	الناتج:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_6311_36" style="">
<span class="pun">+---------------+-----------------+</span><span class="pln">
</span><span class="pun">|</span><span class="pln"> </span><span class="typ">Variable_name</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="typ">Value</span><span class="pln">           </span><span class="pun">|</span><span class="pln">
</span><span class="pun">+---------------+-----------------+</span><span class="pln">
</span><span class="pun">|</span><span class="pln"> have_openssl  </span><span class="pun">|</span><span class="pln"> YES             </span><span class="pun">|</span><span class="pln">
</span><span class="pun">|</span><span class="pln"> have_ssl      </span><span class="pun">|</span><span class="pln"> YES             </span><span class="pun">|</span><span class="pln">
</span><span class="pun">|</span><span class="pln"> ssl_ca        </span><span class="pun">|</span><span class="pln"> ca</span><span class="pun">.</span><span class="pln">pem          </span><span class="pun">|</span><span class="pln">
</span><span class="pun">|</span><span class="pln"> ssl_capath    </span><span class="pun">|</span><span class="pln">                 </span><span class="pun">|</span><span class="pln">
</span><span class="pun">|</span><span class="pln"> ssl_cert      </span><span class="pun">|</span><span class="pln"> server</span><span class="pun">-</span><span class="pln">cert</span><span class="pun">.</span><span class="pln">pem </span><span class="pun">|</span><span class="pln">
</span><span class="pun">|</span><span class="pln"> ssl_cipher    </span><span class="pun">|</span><span class="pln">                 </span><span class="pun">|</span><span class="pln">
</span><span class="pun">|</span><span class="pln"> ssl_crl       </span><span class="pun">|</span><span class="pln">                 </span><span class="pun">|</span><span class="pln">
</span><span class="pun">|</span><span class="pln"> ssl_crlpath   </span><span class="pun">|</span><span class="pln">                 </span><span class="pun">|</span><span class="pln">
</span><span class="pun">|</span><span class="pln"> ssl_key       </span><span class="pun">|</span><span class="pln"> server</span><span class="pun">-</span><span class="pln">key</span><span class="pun">.</span><span class="pln">pem  </span><span class="pun">|</span><span class="pln">
</span><span class="pun">+---------------+-----------------+</span><span class="pln">
</span><span class="lit">9</span><span class="pln"> rows </span><span class="kwd">in</span><span class="pln"> </span><span class="kwd">set</span><span class="pln"> </span><span class="pun">(</span><span class="lit">0.00</span><span class="pln"> sec</span><span class="pun">)</span></pre>

<p>
	نجد أنَّ قيم المتغيرات <code>have_openssl</code> و <code>have_ssl</code> أصبحت <code>YES</code> بدلًا من <code>DISABLED</code>؛ وسنلاحظ وجود قيم مرتبطة بالمتغيرات <code>ssl_ca</code> و <code>ssl_cert</code> و <code>ssl_key</code> وهي أسماء ملفات الشهادات المولَّدة.<br>
	لنتحقق مجددًا من معلومات الاتصال بتنفيذ:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_6311_38" style="">
<span class="pln">\s</span></pre>

<p>
	الناتج:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_6311_40" style="">
<span class="pun">--------------</span><span class="pln">
</span><span class="pun">.</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> </span><span class="pun">.</span><span class="pln">
<abbr title="Secure Socket Layer | طبقة المنافذ الآمنة">SSL</abbr></span><span class="pun">:</span><span class="pln">            </span><span class="typ">Cipher</span><span class="pln"> </span><span class="kwd">in</span><span class="pln"> </span><span class="kwd">use</span><span class="pln"> </span><span class="kwd">is</span><span class="pln"> DHE</span><span class="pun">-</span><span class="pln">RSA</span><span class="pun">-</span><span class="pln">AES256</span><span class="pun">-</span><span class="pln">SHA
</span><span class="pun">.</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> </span><span class="pun">.</span><span class="pln">
</span><span class="typ">Connection</span><span class="pun">:</span><span class="pln">      </span><span class="lit">127.0</span><span class="pun">.</span><span class="lit">0.1</span><span class="pln"> via TCP</span><span class="pun">/</span><span class="pln">IP
</span><span class="pun">.</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> </span><span class="pun">.</span><span class="pln">
</span><span class="pun">--------------</span></pre>

<p>
	أصبح الناتج هذه المرة يشير إلى استخدام تشفير <abbr title="Secure Socket Layer | طبقة المنافذ الآمنة">SSL</abbr> لجعل اتصالنا مع الخادوم آمنًا.<br>
	لنعد إلى سطر الأوامر بالخروج من MySQL:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_6311_42" style="">
<span class="kwd">exit</span></pre>

<p>
	أصبح بإمكان خادومنا الآن تشفير الاتصالات، لكن ما يزال علينا إجراء بعض الضبط الإضافي للسماح بالاتصالات البعيدة وإجبار العملاء على استخدام الاتصالات الآمنة.
</p>

<h2 id="ضبط-الاتصالات-الآمنة-للاتصالات-البعيدة">
	ضبط الاتصالات الآمنة للاتصالات البعيدة
</h2>

<p>
	بعد أن أصبح تشفير <abbr title="Secure Socket Layer | طبقة المنافذ الآمنة">SSL</abbr> متاحًا على الخادوم، يمكننا البدء بضبط الوصول البعيد، وعلينا فعل ما يلي لتحقيق ذلك:
</p>

<ul>
<li>
		جعل استخدام <abbr title="Secure Socket Layer | طبقة المنافذ الآمنة">SSL</abbr> ضروريًا للاتصال.
	</li>
	<li>
		ربط الخادوم ببطاقة شبكية عامة.
	</li>
	<li>
		إنشاء مستخدم MySQL للاتصالات البعيدة.
	</li>
	<li>
		تعديل قواعد الجدار الناري للسماح بالاتصالات الخارجية.
	</li>
</ul>
<h3 id="جعل-استخدام-ssl-ضروريا-لإجراء-الاتصال">
	جعل استخدام <abbr title="Secure Socket Layer | طبقة المنافذ الآمنة">SSL</abbr> ضروريًا لإجراء الاتصال
</h3>

<p>
	أصبح خادوم MySQL مضبوطًا لقبول اتصالات <abbr title="Secure Socket Layer | طبقة المنافذ الآمنة">SSL</abbr> من العملاء؛ لكنه ما يزال يسمح بإجراء اتصالات غير مشفرة إذا طلب العميل ذلك.<br>
	يمكننا حل هذه المشكلة بتفعيل الخيار <code>require_secure_transport</code> الذي لا يسمح إلا بالاتصالات المشفرة عبر <abbr title="Secure Socket Layer | طبقة المنافذ الآمنة">SSL</abbr> أو عبر مقبس Unix محلي؛ ولعدم إتاحة الاتصال عبر المقبس المحلي إلا ضمن الخادوم نفسه، فالحل الوحيد لاتصال العملاء البعيدين هو استخدام <abbr title="Secure Socket Layer | طبقة المنافذ الآمنة">SSL</abbr> للتشفير.
</p>

<p>
	عدِّل ملف <code>‎/etc/mysql/my.cnf</code> باستعمال محررك النصي المفضل لتفعيل هذا الخيار:
</p>

<pre class="ipsCode" id="ips_uid_6311_44">
sudo nano /etc/mysql/my.cnf</pre>

<p>
	ستجد داخل الملف تعليمتَي <code>‎!includedir</code> التي تستخدم لقراءة ملفات الضبط الإضافية، علينا وضع الضبط الخاص بنا تحت تلك الأسطر لتجاوز أيّة تعليمات ضبط موجودة داخل ملفات الضبط الإضافية.<br>
	ابدأ بإنشاء قسم <code>[mysqld]</code> لاستهداف عملية خادوم MySQL، واضبط تحت ترويسة هذا القسم الخيار <code>require_secure_transport</code> إلى <code>ON</code>:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_6311_46" style="">
<span class="pun">.</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> </span><span class="pun">.</span><span class="pln">

</span><span class="pun">!</span><span class="pln">includedir </span><span class="pun">/</span><span class="pln">etc</span><span class="pun">/</span><span class="pln">mysql</span><span class="pun">/</span><span class="pln">conf</span><span class="pun">.</span><span class="pln">d</span><span class="pun">/</span><span class="pln">
</span><span class="pun">!</span><span class="pln">includedir </span><span class="pun">/</span><span class="pln">etc</span><span class="pun">/</span><span class="pln">mysql</span><span class="pun">/</span><span class="pln">mysql</span><span class="pun">.</span><span class="pln">conf</span><span class="pun">.</span><span class="pln">d</span><span class="pun">/</span><span class="pln">

</span><span class="pun">[</span><span class="pln">mysqld</span><span class="pun">]</span><span class="pln">
</span><span class="com"># Require clients to connect either using <abbr title="Secure Socket Layer | طبقة المنافذ الآمنة">SSL</abbr></span><span class="pln">
</span><span class="com"># or through a local socket file</span><span class="pln">
require_secure_transport </span><span class="pun">=</span><span class="pln"> ON</span></pre>

<p>
	لن نحتاج إلى أكثر من هذا السطر لجعل استخدام الاتصالات المشفرة ضروريًا.<br>
	إنَّ خادوم MySQL مضبوطٌ مبدئيًّا للاستماع إلى الاتصالات الآتية من الحاسوب المحلي فقط، وللاستماع إلى الاتصالات البعيدة، فيمكننا ضبط قيمة التعليمة <code>bind-address</code> للإشارة إلى بطاقة شبكية مختلفة.
</p>

<p>
	للسماح لخادوم MySQL بقبول الاتصالات من جميع البطاقات الشبكية، فيمكننا ضبط قيمة التعليمة <code>bind-address</code> إلى <code>0.0.0.0</code>:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_6311_48" style="">
<span class="pun">.</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> </span><span class="pun">.</span><span class="pln">

</span><span class="pun">!</span><span class="pln">includedir </span><span class="pun">/</span><span class="pln">etc</span><span class="pun">/</span><span class="pln">mysql</span><span class="pun">/</span><span class="pln">conf</span><span class="pun">.</span><span class="pln">d</span><span class="pun">/</span><span class="pln">
</span><span class="pun">!</span><span class="pln">includedir </span><span class="pun">/</span><span class="pln">etc</span><span class="pun">/</span><span class="pln">mysql</span><span class="pun">/</span><span class="pln">mysql</span><span class="pun">.</span><span class="pln">conf</span><span class="pun">.</span><span class="pln">d</span><span class="pun">/</span><span class="pln">

</span><span class="pun">[</span><span class="pln">mysqld</span><span class="pun">]</span><span class="pln">
</span><span class="com"># Require clients to connect either using <abbr title="Secure Socket Layer | طبقة المنافذ الآمنة">SSL</abbr></span><span class="pln">
</span><span class="com"># or through a local socket file</span><span class="pln">
require_secure_transport </span><span class="pun">=</span><span class="pln"> ON
bind</span><span class="pun">-</span><span class="pln">address </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0.0</span><span class="pun">.</span><span class="lit">0.0</span></pre>

<p>
	احفظ الملف وأغلقه بعد أن تنتهي من تعديله.<br>
	أعد تشغيل خادوم MySQL لتطبيق الضبط الجديد:
</p>

<pre class="ipsCode" id="ips_uid_6311_50">
sudo systemctl restart mysql</pre>

<p>
	تأكد أنَّ خادوم MySQL يستمع على <code>0.0.0.0</code> بدلًا من <code>127.0.0.1</code> بكتابة:
</p>

<pre class="ipsCode" id="ips_uid_6311_52">
sudo netstat -plunt</pre>

<p>
	الناتج:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_6311_54" style="">
<span class="typ">Active</span><span class="pln"> </span><span class="typ">Internet</span><span class="pln"> connections </span><span class="pun">(</span><span class="pln">only servers</span><span class="pun">)</span><span class="pln">
</span><span class="typ">Proto</span><span class="pln"> </span><span class="typ">Recv</span><span class="pun">-</span><span class="pln">Q </span><span class="typ">Send</span><span class="pun">-</span><span class="pln">Q </span><span class="typ">Local</span><span class="pln"> </span><span class="typ">Address</span><span class="pln">           </span><span class="typ">Foreign</span><span class="pln"> </span><span class="typ">Address</span><span class="pln">         </span><span class="typ">State</span><span class="pln">       <abbr title="Process IDentifier | معرّف العملية أو البرنامج">PID</abbr></span><span class="pun">/</span><span class="typ">Program</span><span class="pln"> name
tcp        </span><span class="lit">0</span><span class="pln">      </span><span class="lit">0</span><span class="pln"> </span><span class="lit">0.0</span><span class="pun">.</span><span class="lit">0.0</span><span class="pun">:</span><span class="lit">3306</span><span class="pln">            </span><span class="lit">0.0</span><span class="pun">.</span><span class="lit">0.0</span><span class="pun">:*</span><span class="pln">               LISTEN      </span><span class="lit">4330</span><span class="pun">/</span><span class="pln">mysqld     
tcp        </span><span class="lit">0</span><span class="pln">      </span><span class="lit">0</span><span class="pln"> </span><span class="lit">0.0</span><span class="pun">.</span><span class="lit">0.0</span><span class="pun">:</span><span class="lit">22</span><span class="pln">              </span><span class="lit">0.0</span><span class="pun">.</span><span class="lit">0.0</span><span class="pun">:*</span><span class="pln">               LISTEN      </span><span class="lit">1874</span><span class="pun">/</span><span class="pln">sshd       
tcp6       </span><span class="lit">0</span><span class="pln">      </span><span class="lit">0</span><span class="pln"> </span><span class="pun">:::</span><span class="lit">22</span><span class="pln">                   </span><span class="pun">:::*</span><span class="pln">                    LISTEN      </span><span class="lit">1874</span><span class="pun">/</span><span class="pln">sshd</span></pre>

<p>
	القيمة <code>0.0.0.0</code> في الناتج السابق تُشير إلى أنَّ خدمة MySQL تستمع إلى الاتصالات في جميع البطاقات الشبكية المتاحة.
</p>

<p>
	علينا بعدئذٍ السماح لاتصالات MySQL عبر الجدار الناري، وذلك بإنشاء استثناء كما يلي:
</p>

<pre class="ipsCode" id="ips_uid_6311_56">
sudo ufw allow mysql</pre>

<p>
	الناتج:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_6311_58" style="">
<span class="typ">Rule</span><span class="pln"> added
</span><span class="typ">Rule</span><span class="pln"> added </span><span class="pun">(</span><span class="pln">v6</span><span class="pun">)</span></pre>

<p>
	يجب أن تتمكن الاتصالات البعيدة من الوصول إلى خادوم MySQL.
</p>

<h3 id="إنشاء-مستخدم-mysql-للاتصالات-البعيدة">
	إنشاء مستخدم MySQL للاتصالات البعيدة
</h3>

<p>
	أصبح خادوم MySQL جاهزًا للاستماع إلى الاتصالات البعيدة، لكننا لا نملك حاليًا أيّ مستخدم مضبوط لكي يتصل من حاسوبٍ آخر.
</p>

<p>
	سجِّل دخولك إلى خادوم MySQL عبر المستخدم <code>root</code>:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_6311_60" style="">
<span class="pln">mysql </span><span class="pun">-</span><span class="pln">u root </span><span class="pun">-</span><span class="pln">p</span></pre>

<p>
	يمكننا الآن إنشاء حساب للمستخدم البعيد عبر الأمر <code>CREATE USER</code>، وسنستخدم عنوان IP لجهاز العميل في قسم المضيف من تعليمة تعريف المستخدم الجديد لجعل الاتصال عبر هذا المستخدم محصورًا بذاك الجهاز.<br>
	ولضمان الاتصال عبر <abbr title="Secure Socket Layer | طبقة المنافذ الآمنة">SSL</abbr> حتى لو عُطِّلَ الخيار <code>require_secure_transport</code> مستقبلًا، فسنُحدِّد في تعليمة تعريف الحساب أنَّه يجب استعمال <abbr title="Secure Socket Layer | طبقة المنافذ الآمنة">SSL</abbr> عند الاتصال باستخدام هذا الحساب بتضمين <code>REQUIRE <abbr title="Secure Socket Layer | طبقة المنافذ الآمنة">SSL</abbr></code>:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_6311_62" style="">
<span class="pln">CREATE USER </span><span class="str">'remote_user'</span><span class="pun">@</span><span class="str">'mysql_client_IP'</span><span class="pln"> IDENTIFIED BY </span><span class="str">'password'</span><span class="pln"> REQUIRE <abbr title="Secure Socket Layer | طبقة المنافذ الآمنة">SSL</abbr></span><span class="pun">;</span></pre>

<p>
	علينا بعد ذلك أن نمنح المستخدم صلاحيات على قواعد البيانات أو الجداول التي ينبغي له الوصول إليها؛ وسنُنشِئ قاعدة بيانات لشرح هذه الفكرة باسم <code>example</code> وسنمنح مستخدمنا ملكيتها:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_6311_64" style="">
<span class="pln">CREATE DATABASE example</span><span class="pun">;</span><span class="pln">
GRANT ALL ON example</span><span class="pun">.*</span><span class="pln"> TO </span><span class="str">'remote_user'</span><span class="pun">@</span><span class="str">'mysql_client_IP'</span><span class="pun">;</span></pre>

<p>
	علينا تحديث جداول الصلاحيات لتطبيق التعديلات مباشرةً:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_6311_66" style="">
<span class="pln">FLUSH PRIVILEGES</span><span class="pun">;</span></pre>

<p>
	أغلِق جلسة MySQL بعد أن تنتهي من تنفيذ الأوامر السابقة:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_6311_68" style="">
<span class="kwd">exit</span></pre>

<h3 id="اختبار-الاتصالات-البعيدة">
	اختبار الاتصالات البعيدة
</h3>

<p>
	لاختبار إمكانية إجراء اتصال من جهاز العميل إلى الخادوم بنجاح، فاستخدم الخيار <code>‎-u</code> لتحديد اسم المستخدم البعيد، والخيار <code>‎-h</code> لتحديد عنوان IP لخادوم MySQL:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_6311_70" style="">
<span class="pln">mysql </span><span class="pun">-</span><span class="pln">u remote_user </span><span class="pun">-</span><span class="pln">p </span><span class="pun">-</span><span class="pln">h mysql_server_IP</span></pre>

<p>
	بعد كتابتك لكلمة المرور، فستسجل دخولك إلى الخادوم البعيد.<br>
	نفذ الأمر الآتي للتأكد من أنَّ اتصالك آمن:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_6311_72" style="">
<span class="pln">\s</span></pre>

<p>
	الناتج:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_6311_74" style="">
<span class="pun">--------------</span><span class="pln">
</span><span class="pun">.</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> </span><span class="pun">.</span><span class="pln">
<abbr title="Secure Socket Layer | طبقة المنافذ الآمنة">SSL</abbr></span><span class="pun">:</span><span class="pln">         </span><span class="typ">Cipher</span><span class="pln"> </span><span class="kwd">in</span><span class="pln"> </span><span class="kwd">use</span><span class="pln"> </span><span class="kwd">is</span><span class="pln"> DHE</span><span class="pun">-</span><span class="pln">RSA</span><span class="pun">-</span><span class="pln">AES256</span><span class="pun">-</span><span class="pln">SHA
</span><span class="pun">.</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> </span><span class="pun">.</span><span class="pln">
</span><span class="typ">Connection</span><span class="pun">:</span><span class="pln">      mysql_server_IP via TCP</span><span class="pun">/</span><span class="pln">IP
</span><span class="pun">.</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> </span><span class="pun">.</span><span class="pln">
</span><span class="pun">--------------</span></pre>

<p>
	اخرج من عميل MySQL وعد إلى سطر الأوامر:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_6311_76" style="">
<span class="kwd">exit</span></pre>

<p>
	جرِّب الآن الاتصال بطريقة غير آمنة إلى الخادوم:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_6311_78" style="">
<span class="pln">mysql </span><span class="pun">-</span><span class="pln">u remote_user </span><span class="pun">-</span><span class="pln">p </span><span class="pun">-</span><span class="pln">h mysql_server_IP </span><span class="pun">–</span><span class="pln"><abbr title="Secure Socket Layer | طبقة المنافذ الآمنة">ssl</abbr></span><span class="pun">-</span><span class="pln">mode</span><span class="pun">=</span><span class="pln">disabled</span></pre>

<p>
	بعد أن يُطلَب منك إدخال كلمة المرور، فستجد أنَّ الاتصال قد رُفِض:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_6311_80" style="">
<span class="pln">ERROR </span><span class="lit">1045</span><span class="pln"> </span><span class="pun">(</span><span class="lit">28000</span><span class="pun">):</span><span class="pln"> </span><span class="typ">Access</span><span class="pln"> denied </span><span class="kwd">for</span><span class="pln"> user </span><span class="str">'remote_user'</span><span class="pun">@</span><span class="str">'mysql_server_IP'</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">using</span><span class="pln"> password</span><span class="pun">:</span><span class="pln"> YES</span><span class="pun">)</span></pre>

<p>
	هذا ما بدأنا درسنا محاولين إنجازه: فالاتصالات المشفرة عبر <abbr title="Secure Socket Layer | طبقة المنافذ الآمنة">SSL</abbr> إلى الخادوم مسموحة، والاتصالات غير المشفرة ممنوعة.<br>
	لهذا الحد، أصبح خادوم MySQL مضبوطًا للسماح بالاتصالات البعيدة الآمنة؛ ويمكنك أن تتوقف عند هذه النقطة إذا كان ذلك يلبي احتياجاتك الأمنية، لكن هنالك المزيد من الأمور التي يمكنك فعلها لزيادة الحماية.
</p>

<h2 id="ضبط-التحقق-من-الاتصالات-الآتية-إلى-خادوم-mysql">
	ضبط التحقق من الاتصالات الآتية إلى خادوم MySQL
</h2>

<p>
	إنَّ خادوم MySQL مضبوطٌ حاليًا مع شهادة <abbr title="Secure Socket Layer | طبقة المنافذ الآمنة">SSL</abbr> موقعة من سلطة شهادات محلية (Local certificate authority)؛ والشهادة والمفتاح الخاصَين بالخادوم كافيان لتشفير الاتصالات القادمة إلى الخادوم.
</p>

<p>
	لكننا لم نستفد من «الثقة» التي يمكن لسلطة الشهادات توفيرها، فعند توزيع شهادة سلطة الشهادات إلى العملاء، إضافةً إلى شهادة ومفتاح خاصَين بالعميل، فيمكن لكلا الطرفين التأكد أنَّ الشهادات موقعة من سلطة شهادات موثوقة. يمكن أن يساعد ذلك بمنع الاتصالات المزورة إلى أجهزة خبيثة.<br>
	لتطبيق هذا النوع من الحماية الإضافية، فسنحتاج إلى:
</p>

<ul>
<li>
		نقل ملفات <abbr title="Secure Socket Layer | طبقة المنافذ الآمنة">SSL</abbr> الملائمة إلى جهاز العميل
	</li>
	<li>
		إنشاء ملف ضبط للعميل
	</li>
	<li>
		تعديل حساب المستخدم البعيد لطلب وجود شهادة موثوقة
	</li>
</ul>
<h3 id="نقل-شهادات-العميل-إلى-جهازه">
	نقل شهادات العميل إلى جهازه
</h3>

<p>
	علينا بادئ الأمر الحصول على شهادة سلطة الشهادات التابعة لخادوم MySQL مع ملفات شهادات العميل ووضعها في جهاز العميل.<br>
	سنبدأ بفعل ذلك بإنشاء مجلد باسم <code>client-<abbr title="Secure Socket Layer | طبقة المنافذ الآمنة">ssl</abbr></code> في جهاز العميل في مجلد المنزل للمستخدم الذي ستستعمله للاتصال:
</p>

<pre class="ipsCode" id="ips_uid_6311_82">
mkdir ~/client-<abbr title="Secure Socket Layer | طبقة المنافذ الآمنة">ssl</abbr></pre>

<p>
	ولأنَّ مفتاح الشهادة هو ملفٌ حساس، فعلينا قفل الوصول إلى المجلد لكي لا يتمكن أي شخصٍ سوى المستخدم المالك له من الوصول إليه:
</p>

<pre class="ipsCode" id="ips_uid_6311_84">
chmod 700 ~/client-<abbr title="Secure Socket Layer | طبقة المنافذ الآمنة">ssl</abbr></pre>

<p>
	يمكننا الآن نسخ معلومات الشهادة إلى مجلدٍ جديد.<br>
	اعرض محتوى شهادة سلطة الشهادات في خادوم MySQL بكتابة الأمر الآتي:
</p>

<pre class="ipsCode" id="ips_uid_6311_86">
sudo cat /var/lib/mysql/ca.pem</pre>

<p>
	الناتج:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_6311_88" style="">
<span class="pun">-----</span><span class="kwd">BEGIN</span><span class="pln"> CERTIFICATE</span><span class="pun">-----</span><span class="pln">

</span><span class="pun">.</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> </span><span class="pun">.</span><span class="pln">

</span><span class="pun">-----</span><span class="kwd">END</span><span class="pln"> CERTIFICATE</span><span class="pun">-----</span></pre>

<p>
	انسخ جميع المحتوى بما فيه الأسطر التي فيها <code>BEGIN CERTIFICATE</code> و <code>END CERTIFICATE</code> إلى الحافظة.<br>
	أنشِئ ملفًا جديدًا في جهاز العميل باستعمال الأمر الآتي:
</p>

<pre class="ipsCode" id="ips_uid_6311_90">
nano ~/client-<abbr title="Secure Socket Layer | طبقة المنافذ الآمنة">ssl</abbr>/ca.pem</pre>

<p>
	ألصق محتوى الشهادة المنسوخ في ذاك الملف، ثم احفظه وأغلق الملف عندما تنتهي منه.<br>
	علينا الآن عرض محتوى شهادة العميل في خادوم MySQL:
</p>

<pre class="ipsCode" id="ips_uid_6311_92">
sudo cat /var/lib/mysql/client-cert.pem</pre>

<p>
	الناتج:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_6311_94" style="">
<span class="pun">-----</span><span class="kwd">BEGIN</span><span class="pln"> CERTIFICATE</span><span class="pun">-----</span><span class="pln">

</span><span class="pun">.</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> </span><span class="pun">.</span><span class="pln">

</span><span class="pun">-----</span><span class="kwd">END</span><span class="pln"> CERTIFICATE</span><span class="pun">-----</span></pre>

<p>
	انسخ محتوياته مجددًا، واحرص على تضمين أول وآخر سطر.<br>
	أنشِئ ملفًا جديدًا في عميل MySQL بالاسم نفسه ضمن مجلد <code>client-<abbr title="Secure Socket Layer | طبقة المنافذ الآمنة">ssl</abbr></code>:
</p>

<pre class="ipsCode" id="ips_uid_6311_96">
nano ~/client-<abbr title="Secure Socket Layer | طبقة المنافذ الآمنة">ssl</abbr>/client-cert.pem</pre>

<p>
	ألصق محتويات الحافظة إلى الملف، ثم احفظه وأغلقه.
</p>

<p>
	ثم اعرض محتويات مفتاح العميل على خادوم MySQL:
</p>

<pre class="ipsCode" id="ips_uid_6311_98">
sudo cat /var/lib/mysql/client-key.pem</pre>

<p>
	الناتج:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_6311_100" style="">
<span class="pun">-----</span><span class="kwd">BEGIN</span><span class="pln"> RSA PRIVATE KEY</span><span class="pun">-----</span><span class="pln">

</span><span class="pun">.</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> </span><span class="pun">.</span><span class="pln">

</span><span class="pun">-----</span><span class="kwd">END</span><span class="pln"> RSA PRIVATE KEY</span><span class="pun">-----</span></pre>

<p>
	انسخ محتوياته مجددًا إلى حافظتك، واحرص على تضمين أول وآخر سطر.<br>
	أنشِئ ملفًا جديدًا في عميل MySQL بالاسم نفسه ضمن مجلد <code>client-<abbr title="Secure Socket Layer | طبقة المنافذ الآمنة">ssl</abbr></code>:
</p>

<pre class="ipsCode" id="ips_uid_6311_102">
nano ~/client-<abbr title="Secure Socket Layer | طبقة المنافذ الآمنة">ssl</abbr>/client-key.pem</pre>

<p>
	ألصق محتويات الحافظة إلى الملف، ثم احفظه وأغلقه.<br>
	يجب يكون في جهاز العميل جميع الشهادات اللازمة للوصول إلى خادوم MySQL؛ وعلينا الآن تعديل حساب المستخدم.
</p>

<h3 id="تعديل-حساب-المستخدم-البعيد-لطلب-وجود-شهادة-موثوقة">
	تعديل حساب المستخدم البعيد لطلب وجود شهادة موثوقة
</h3>

<p>
	أصبح لدى عميل MySQL الملفات اللازمة للتحقق من الشهادة عند الاتصال بخادوم MySQL، لكن الخادوم ليس مضبوطًا بعد لطلب وجود شهادة للعميل من سلطة شهادات موثوقة.<br>
	لتعديل ذلك، علينا تسجيل الدخول عبر المستخدم <code>root</code> في خادوم MySQL:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_6311_104" style="">
<span class="pln">mysql </span><span class="pun">-</span><span class="pln">u root </span><span class="pun">-</span><span class="pln">p</span></pre>

<p>
	سنحتاج إلى تعديل المتطلبات الخاصة بالمستخدم البعيد، فبدلًا من استعمال عبارة <code>REQUIRE <abbr title="Secure Socket Layer | طبقة المنافذ الآمنة">SSL</abbr></code> علينا استعمال عبارة <code>REQUIRE X509</code> والتي ستُطبِّق الإجراءات الأمنية نفسها، لكنها ستتطلب أيضًا أن يملك العميل شهادةً موقعةً من سلطة شهادات يثق بها خادوم MySQL.
</p>

<p>
	علينا استعمال الأمر <code>ALTER USER</code> لتعديل المتطلبات الخاصة بالمستخدم:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_6311_106" style="">
<span class="pln">ALTER USER </span><span class="str">'remote_user'</span><span class="pun">@</span><span class="str">'mysql_client_IP'</span><span class="pln"> REQUIRE X509</span><span class="pun">;</span></pre>

<p>
	ثم حدِّث جداول الصلاحيات لتأخذ التعديلات مجراها مباشرةً:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_6311_108" style="">
<span class="pln">FLUSH PRIVILEGES</span><span class="pun">;</span></pre>

<p>
	اخرج من سطر أوامر MySQL عندما تنتهي بالأمر:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_6311_110" style="">
<span class="kwd">exit</span></pre>

<p>
	سنتأكد في الخطوة التالية أننا ما زلنا نستطيع الاتصال.
</p>

<h3 id="تجربة-التحقق-من-الشهادة-عند-الاتصال">
	تجربة التحقق من الشهادة عند الاتصال
</h3>

<p>
	من المناسب الآن معرفة أنَّ كلا الطرفين سيستطيع التحقق من شهادة الآخر عند الاتصال.<br>
	لنحاول أولًا الاتصال من عميل MySQL دون توفير شهادات له:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_6311_112" style="">
<span class="pln">mysql </span><span class="pun">-</span><span class="pln">u remote_user </span><span class="pun">-</span><span class="pln">p </span><span class="pun">-</span><span class="pln">h mysql_server_IP</span></pre>

<p>
	الناتج:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_6311_114" style="">
<span class="pln">ERROR </span><span class="lit">1045</span><span class="pln"> </span><span class="pun">(</span><span class="lit">28000</span><span class="pun">):</span><span class="pln"> </span><span class="typ">Access</span><span class="pln"> denied </span><span class="kwd">for</span><span class="pln"> user </span><span class="str">'remote_user'</span><span class="pun">@</span><span class="str">'mysql_client_IP'</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">using</span><span class="pln"> password</span><span class="pun">:</span><span class="pln"> YES</span><span class="pun">)</span></pre>

<p>
	سيرفض الخادوم الاتصال إذا لم نوفِّر شهادة للعميل.
</p>

<p>
	حاول الآن الاتصال مع توفير الخيارات <code>‎--<abbr title="Secure Socket Layer | طبقة المنافذ الآمنة">ssl</abbr>-ca</code> و <code>‎--<abbr title="Secure Socket Layer | طبقة المنافذ الآمنة">ssl</abbr>-cert</code> و <code>‎--<abbr title="Secure Socket Layer | طبقة المنافذ الآمنة">ssl</abbr>-key</code> للإشارة إلى الملفات الموافقة لها والموجودة في مجلد <code>‎~/client-<abbr title="Secure Socket Layer | طبقة المنافذ الآمنة">ssl</abbr></code>:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_6311_116" style="">
<span class="pln">mysql </span><span class="pun">-</span><span class="pln">u remote_user </span><span class="pun">-</span><span class="pln">p </span><span class="pun">-</span><span class="pln">h mysql_server_IP </span><span class="pun">--</span><span class="pln"><abbr title="Secure Socket Layer | طبقة المنافذ الآمنة">ssl</abbr></span><span class="pun">-</span><span class="pln">ca</span><span class="pun">=~</span><span class="str">/client-<abbr title="Secure Socket Layer | طبقة المنافذ الآمنة">ssl</abbr>/</span><span class="pln">ca</span><span class="pun">.</span><span class="pln">pem </span><span class="pun">--</span><span class="pln"><abbr title="Secure Socket Layer | طبقة المنافذ الآمنة">ssl</abbr></span><span class="pun">-</span><span class="pln">cert</span><span class="pun">=~</span><span class="str">/client-<abbr title="Secure Socket Layer | طبقة المنافذ الآمنة">ssl</abbr>/</span><span class="pln">client</span><span class="pun">-</span><span class="pln">cert</span><span class="pun">.</span><span class="pln">pem </span><span class="pun">–</span><span class="pln"><abbr title="Secure Socket Layer | طبقة المنافذ الآمنة">ssl</abbr></span><span class="pun">-</span><span class="pln">key</span><span class="pun">=~</span><span class="str">/client-<abbr title="Secure Socket Layer | طبقة المنافذ الآمنة">ssl</abbr>/</span><span class="pln">client</span><span class="pun">-</span><span class="pln">key</span><span class="pun">.</span><span class="pln">pem</span></pre>

<p>
	يجب أن تستطيع تسجيل الدخول إلى خادوم MySQL بنجاح. يمكنك العودة إلى سطر الأوامر بتنفيذ:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_6311_118" style="">
<span class="kwd">exit</span></pre>

<p>
	لقد تأكدنا الآن من القدرة على الوصول إلى الخادوم، لكن يمكننا تحسين قابلية الوصول إليه بإنشاء ملف ضبط.
</p>

<h3 id="إنشاء-ملف-ضبط-لعميل-mysql">
	إنشاء ملف ضبط لعميل MySQL
</h3>

<p>
	لتجنب تحديد ملفات الشهادات في كل مرة نتصل فيها إلى الخادوم، فيمكننا إنشاء ملف ضبط بسيط لعميل MySQL.<br>
	أنشِئ ملفا مخفيًا في مجلد المنزل في عميل MySQL باسم <code>‎~/.my.cnf</code>:
</p>

<pre class="ipsCode" id="ips_uid_6311_120">
nano ~/.my.cnf</pre>

<p>
	أنشِئ في بداية ذاك الملف قسمًا باسم <code>[client]</code>، ويمكننا بعد ذلك السطر إضافة الخيارات <code><abbr title="Secure Socket Layer | طبقة المنافذ الآمنة">ssl</abbr>-ca</code> و <code><abbr title="Secure Socket Layer | طبقة المنافذ الآمنة">ssl</abbr>-cert</code> و <code><abbr title="Secure Socket Layer | طبقة المنافذ الآمنة">ssl</abbr>-key</code> للإشارة إلى الملفات التي نسخناها من الخادوم؛ يجب أن يبدو شكل الملف كالآتي:
</p>

<pre class="ipsCode" id="ips_uid_6311_122">
[client]
<abbr title="Secure Socket Layer | طبقة المنافذ الآمنة">ssl</abbr>-ca = ~/client-<abbr title="Secure Socket Layer | طبقة المنافذ الآمنة">ssl</abbr>/ca.pem
<abbr title="Secure Socket Layer | طبقة المنافذ الآمنة">ssl</abbr>-cert = ~/client-<abbr title="Secure Socket Layer | طبقة المنافذ الآمنة">ssl</abbr>/client-cert.pem
<abbr title="Secure Socket Layer | طبقة المنافذ الآمنة">ssl</abbr>-key = ~/client-<abbr title="Secure Socket Layer | طبقة المنافذ الآمنة">ssl</abbr>/client-key.pem</pre>

<p>
	يُخبِر الخيار <code><abbr title="Secure Socket Layer | طبقة المنافذ الآمنة">ssl</abbr>-ca</code> العميل أن يتحقق أنَّ الشهادة التي وفرها خادوم MySQL موقعةٌ من سلطة الشهادات التي أشرنا إلى شهادتها. وهذا يجعل العميل متأكدًا أنه يتصل بخادوم MySQL موثوق.
</p>

<p>
	أما الخياران <code><abbr title="Secure Socket Layer | طبقة المنافذ الآمنة">ssl</abbr>-cert</code> و <code><abbr title="Secure Socket Layer | طبقة المنافذ الآمنة">ssl</abbr>-key</code> فيشيران إلى الملفات اللازمة لإثبات أنَّ العميل يملك شهادة موقعة من سلطة الشهادات نفسها. سنحتاج إلى ذلك إذا أردنا في خادوم MySQL التحقق أنَّ العميل موثوق من سلطة الشهادات أيضًا.<br>
	احفظ الملف وأغلقه عندما تنتهي من التعديلات عليه.
</p>

<p>
	يمكنك الآن الاتصال إلى خادوم MySQL دون إضافة الخيارات <code>‎--<abbr title="Secure Socket Layer | طبقة المنافذ الآمنة">ssl</abbr>-ca</code> و <code>‎--<abbr title="Secure Socket Layer | طبقة المنافذ الآمنة">ssl</abbr>-cert</code> و <code>‎--<abbr title="Secure Socket Layer | طبقة المنافذ الآمنة">ssl</abbr>-key</code> في سطر الأوامر:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_6311_124" style="">
<span class="pln">mysql </span><span class="pun">-</span><span class="pln">u remote_user </span><span class="pun">-</span><span class="pln">p </span><span class="pun">-</span><span class="pln">h mysql_server_ip </span></pre>

<p>
	يجب أن يملك الخادوم والعميل الآن الشهادات اللازمة للاتصال بأمان، وضبطنا كلا الطرفين للتحقق أنَّ الشهادة موقعة من سلطة الشهادات الموثوقة.
</p>

<h2 id="الخلاصة">
	الخلاصة
</h2>

<p>
	يجب أن يكون خادومك مضبوطًا لقبول الاتصالات الآمنة من العملاء البعيدين. وإذا اتبعتَ الخطوات اللازمة للتحقق من الشهادات عبر سلطة الشهادات فسيتأكد كلا الطرفين من وثوقية الطرف الآخر.
</p>

<p>
	ترجمة –وبتصرّف– للمقال <a href="https://www.digitalocean.com/community/tutorials/how-to-configure-ssl-tls-for-mysql-on-ubuntu-16-04" rel="external nofollow">How To Configure <abbr title="Secure Socket Layer | طبقة المنافذ الآمنة">SSL</abbr>/<abbr title="Transport Layer Security | بروتوكول أمن طبقة النقل">TLS</abbr> for MySQL on Ubuntu 16.04</a> لصاحبه Justin Ellingwood
</p>
]]></description><guid isPermaLink="false">341</guid><pubDate>Sat, 26 Aug 2017 13:34:31 +0000</pubDate></item><item><title>&#x645;&#x627; &#x639;&#x644;&#x64A;&#x643; &#x645;&#x639;&#x631;&#x641;&#x62A;&#x647; &#x639;&#x646; &#x62D;&#x642;&#x648;&#x644; JSON &#x641;&#x64A; &#x642;&#x648;&#x627;&#x639;&#x62F; &#x628;&#x64A;&#x627;&#x646;&#x627;&#x62A; MySQL</title><link>https://academy.hsoub.com/devops/servers/databases/mysql/%D9%85%D8%A7-%D8%B9%D9%84%D9%8A%D9%83-%D9%85%D8%B9%D8%B1%D9%81%D8%AA%D9%87-%D8%B9%D9%86-%D8%AD%D9%82%D9%88%D9%84-json-%D9%81%D9%8A-%D9%82%D9%88%D8%A7%D8%B9%D8%AF-%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-mysql-r340/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2017_08/599e805e97f5e_main(18).png.20ac7cbca1cfe52a15e0c6337e1ce615.png" /></p>

<p>
	سهّل محرك قواعد بيانات MySQL من استخدام <a href="https://academy.hsoub.com/devops/servers/databases/%D9%85%D9%82%D8%A7%D8%B1%D9%86%D8%A9-%D8%A8%D9%8A%D9%86-%D8%A3%D9%86%D8%B8%D9%85%D8%A9-%D8%A5%D8%AF%D8%A7%D8%B1%D8%A9-%D9%82%D9%88%D8%A7%D8%B9%D8%AF-%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-%D8%A7%D9%84%D8%B9%D9%84%D8%A7%D9%82%D9%8A%D8%A9-sqlite-%D9%85%D8%B9-mysql-%D9%85%D8%B9-postgresql-r72/" rel="">قواعد البيانات العلاقية Relational</a>، وألغى – إلى حدٍ ما – الخطوط التي تفصل بين قواعد بيانات <a href="https://academy.hsoub.com/devops/servers/databases/%D8%B4%D8%B1%D8%AD-%D8%A7%D9%84%D9%81%D8%B1%D9%88%D9%82%D8%A7%D8%AA-%D8%A8%D9%8A%D9%86-%D9%82%D9%88%D8%A7%D8%B9%D8%AF-%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-sql-%D9%88%D9%86%D8%B8%D9%8A%D8%B1%D8%A7%D8%AA%D9%87%D8%A7-nosql-r71/" rel="">SQL و NoSQL</a> بعد أن أضاف حقلًا لنوع البيانات JSON.
</p>

<p>
	في يومٍ من الأيام السالفة، كان هناك حاسوب وحيدٌ، ثم أتى أحدهم وبنى آخر، وأراد أن ينقل بعض الشفرات من الحاسوب الأول، ولهذا السبب احتجنا إلى طريقةٍ لنقل المعلومات دون اعتمادها على العتاد الذي يُشغِّلُها؛ ومن ذلك الوقت وإلى الآن انتشرت الكثير من <a href="https://academy.hsoub.com/programming/general/%D9%85%D8%A7%D9%84%D9%81%D8%B1%D9%82-%D8%A8%D9%8A%D9%86-%D8%A7%D9%84%D8%AA%D8%B1%D9%85%D9%8A%D8%B2-encoding%D8%8C-%D8%A7%D9%84%D8%AA%D8%B9%D9%85%D9%8A%D8%A9-encryption%D8%8C-%D8%A7%D9%84%D8%AA%D8%AC%D8%B2%D8%A6%D8%A9-hashing-%D9%88%D8%A7%D9%84%D8%AA%D8%B4%D9%88%D9%8A%D8%B4-obfuscation%D8%9F-r308/" rel="">ترميزات المحارف</a> مثل ASCII و EBCIDC و SGML و XML …إلخ. وسطع نجمها لفترةٍ من الزمن.
</p>

<p>
	ولكن في السنوات الأخيرة اشتهرت صيغة JSON (أي JavaScript Object Notation) التي تستعمل لتبادل البيانات بصيغةٍ مهيكلة.
</p>

<p>
	كان نظام قواعد البيانات MySQL قبل الإصدار 5.7 يخزّن مستندًا مُصاغًا بصيغة JSON في حقلٍ نصي، لكن من الصعب البحث في السلاسل النصية الطويلة، وكتابة <a href="https://academy.hsoub.com/devops/linux/%D9%85%D9%82%D8%AF%D9%85%D8%A9-%D9%81%D9%8A-%D8%A7%D9%84%D8%AA%D8%B9%D8%A7%D8%A8%D9%8A%D8%B1-%D8%A7%D9%84%D9%86%D9%85%D8%B7%D9%8A%D8%A9-regular-expressions-r63/" rel="">تعبير نمطي Regular expression</a> للعثور على القيم ضمن تلك السلاسل سيكون أمرًا صعبًا، وإذا غيّرت قيمة من القيم المخزنة ضمن سلسلة JSON فعليك إعادة كتابة السلسلة كلها، وهذا لا يصب في صالح الأداء، لكنه ضروريٌ إذا كنت تعمل على إصدار MySQL 5.6 وما قبله.
</p>

<h2 id="نوع-البيانات-json-في-قواعد-mysql">
	نوع البيانات JSON في قواعد MySQL
</h2>

<p>
	أُضيفَ نوعٌ جديدٌ من أنواع البيانات في الإصدار MySQl 5.7 ألا وهو JSON، فقد أصبح مثل الأرقام الصحيحة، والسلاسل النصية …إلخ. وبهذا أصبحت هنالك طريقةٌ لتخزين مستند JSON كامل في عمودٍ من أعمدة جدول في قاعدة البيانات، وقد يكون حجم هذا المستند مقدرًا بالغيغابايت!
</p>

<p>
	يتحقق الخادوم أنَّ القيمة المُراد تخزينها في هذا الحقل هي مستند JSON صالح، ومن ثم يحفظه بصيغةٍ ثنائية Binary صُمِّمَت خصيصًا لتسهيل البحث فيها؛ يجدر بالذكر أنَّ نوع البيانات الجديد كان السبب في تحديث نسخة MySQL العاملة في مختلف الخواديم أكثر من أيّ ميزة أخرى.
</p>

<p>
	يأتي نوع البيانات الجديد مدعّمًا بأكثر من 20 دالة، وهذه الدوال تستطيع أن تستخلص أزواج «المفتاح-القيمة» Key-value من المستند، أو تحدِّث البيانات، أو توفِّر بيانات وصفية Metadata حول البيانات المخزنة، وتخرج الأعمدة التي ليست بصيغة JSON إلى صيغة JSON، والكثير…<br>
	إصدار MySQL 8 أصبح في مرحلة Milestone release وسيضيف ميزات ودوال جديد. الدالة <code>JSON_PRETTY_PRINT</code> ستؤدي إلى إظهار المخرجات بتنسيق يُسهِّل فهمها؛ وستُضاف تحسينات أخرى مثل إمكانية تعديل البيانات دون إعادة كتابة المستند بأكمله.
</p>

<p>
	كان حفظ البيانات بصيغةٍ غير منسقة يعدّ من ميزات NoSQL، لكن الكثير من قواعد البيانات العلاقية مثل Oracle و SOL Server و <a href="https://academy.hsoub.com/devops/servers/databases/postgresql/" rel="">PostgreSQL</a> وغيرها قد أضافت نوع البيانات JSON، مما يُصعِّب تعريف الفرق بين قواعد بيانات NoSQL و SQL.
</p>

<h2 id="لماذا-علينا-الاهتمام-بميزة-document-store">
	لماذا علينا الاهتمام بميزة Document Store
</h2>

<p>
	بعد أن ظهر نوع البيانات JSON بفترةٍ قصيرة، ظهرت ميزة MySQL Document Store، والتي صُمِّمَت للمبرمجين الذين لا يعرفون لغة الاستعلام البنيوية (SQL) لكنهم يريدون استخدام قواعد البيانات.
</p>

<p>
	يُنشِئ المُطوِّر بنى البيانات ويُطبِّق دوال إنشاء البيانات والحصول عليها وتحديثها وحذفها (تُختَصر هذه العمليات عادةً بالاختصار CRUD) على البيانات وفقًا لحاجته باستعمال لغة البرمجة التي يشاء (مثل Java و JavaScript و Node.js و Python و ‎C++‎ وستُتاح الميزة للغات الأخرى قريبًا).
</p>

<p>
	ليس من الضروري أن يعرف المُطوِّر لغةَ SQL، ولن يلقيَ بالًا إلى أنَّ لغة SQL ستُستعمَل وراء الكواليس؛ حيث ستُخزَّن البيانات في عمود JSON، وبهذه الطريقة يستطيع المطورون استخدام البيانات وحفظها دون الحاجة إلى إنشاء جداول في قاعدة البيانات، ولا إلى تضييع الوقت في التخطيط لقاعدة البيانات، ولا إلى انتظار مدير قواعد البيانات لكي يُنشِئها لهم.
</p>

<p>
	يجب ألّا ننسى أنَّ أغلبية المشاريع تبدأ دون معرفة كيف ستبدو البيانات بعد إطلاق المشروع، وستتطور بنية تلك البيانات مع مرور الزمن لملائمة مختلف الظروف والحاجات.
</p>

<p>
	إذا احتجنا إلى إنشاء قاعدة بيانات علاقية تقليدية من مستندات JSON، فمن السهل استخراج المفاتيح وتحويلها إلى أعمدة لكي تعمل عليها SQL القياسية، ويلي ذلك فهرسة الأعمدة الناتجة لتسريع عملية البحث فيها.
</p>

<h2 id="الجوانب-السلبية">
	الجوانب السلبية
</h2>

<p>
	إنَّ صيغة JSON ممتازةٌ لتخزين البيانات بصيغةٍ «غير رسمية»، لكن قواعد البيانات العلاقية ملائمةٌ للبيانات المُقسَّمة إلى أقسام صغيرة يسهل الوصول إليها.<br>
	أضف إلى ذلك عدم القدرة على فرض معايير دقيقة لتخزين البيانات، فيمكن أن يكون اسم المفتاح الذي يُخزِّن عنوان البريد الإلكتروني <code>email</code> أو <code>eMail</code> أو <code>e-mail</code> أو غير ذلك؛ لكن لا أظن أنَّ هذا الأمر سيُشكِّل عائقًا أمامك إذا كنتَ مدركًا له مسبقًا.<br>
	إذا كنتَ جاهزًا لتجربة حقل JSON، <a href="https://dev.mysql.com/downloads/" rel="external nofollow">فنزِّل MySQL</a>، ونزِّل بطريقك برمجية <a href="https://dev.mysql.com/downloads/workbench/" rel="external nofollow">MySQL Workbench</a> حيث تدعم أعمدة JSON، وكلا البرمجيتين متاحتان مجانًا.
</p>

<p>
	ترجمة – بتصرّف – للمقال <a href="https://opensource.com/article/17/5/mysql-json" rel="external nofollow">What you need to know about JSON in MySQL</a> لصاحبه Dave Stokes.
</p>
]]></description><guid isPermaLink="false">340</guid><pubDate>Thu, 24 Aug 2017 07:30:18 +0000</pubDate></item><item><title>&#x643;&#x64A;&#x641; &#x62A;&#x62B;&#x628;&#x651;&#x62A; MySQL Workbench &#x648;&#x62A;&#x633;&#x62A;&#x62E;&#x62F;&#x645;&#x647; &#x644;&#x644;&#x627;&#x62A;&#x635;&#x627;&#x644; &#x628;&#x642;&#x648;&#x627;&#x639;&#x62F; &#x628;&#x64A;&#x627;&#x646;&#x627;&#x62A; MySQL</title><link>https://academy.hsoub.com/devops/servers/databases/mysql/%D9%83%D9%8A%D9%81-%D8%AA%D8%AB%D8%A8%D9%91%D8%AA-mysql-workbench-%D9%88%D8%AA%D8%B3%D8%AA%D8%AE%D8%AF%D9%85%D9%87-%D9%84%D9%84%D8%A7%D8%AA%D8%B5%D8%A7%D9%84-%D8%A8%D9%82%D9%88%D8%A7%D8%B9%D8%AF-%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-mysql-r324/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2017_07/Untitled-3.png.56a0c5f7f95dc4dfacdba03ab74d0ae2.png" /></p>

<p>
	إن كنت مدير قواعد بيانات DBA فإنه من المحتمل جدًّا أن يكون سطرُ الأوامر هو وسيلتك للتخاطب مع قواعد البيانات التي تديرها. يستزف استخدام سطر الأوامر الوقت عندما تحتاج للاتّصال بقواعد بيانات عدّة تعمل على مضيفات متباعدة؛ استخدامُ واجهة رسوميّة مفيد في هذه الحالة.
</p>

<p>
	يمكنك بالطبع تثبيت <a href="https://academy.hsoub.com/devops/servers/databases/mysql/%D9%83%D9%8A%D9%81-%D8%AA%D9%8F%D8%AB%D8%A8%D9%91%D9%90%D8%AA-%D9%88%D8%AA%D8%A4%D9%85%D9%91%D9%90%D9%86-phpmyadmin-%D8%B9%D9%84%D9%89-ubuntu-1404-r35/" rel="">phpMyAdmin</a> على كلّ خادوم، إلا أنك ستحتاج إلى تسجيل الدخول إلى واجهة وِب مختلفة بالنسبة لكلّ خادوم. ماذا لو كانت لديك واجهة وحيدة للاتّصال بجميع قواعد بيانات <a href="https://academy.hsoub.com/devops/servers/databases/mysql/" rel="">MySQL</a> التي تديرها؟ إن كان هذا ما تبحث عنه فأنت في المكان الصّحيح.
</p>

<p>
	MySQL Workbench هو واجهة رسومية موَّحدة للتعامل مع قواعد بيانات MySQL، توفّر لمعماريّي البرمجيّات Architects، المطوّرين ومديري الأنظمة آليّة فعّالة للتعامل مع قواعد بيانات متعدّدة على مضيفات متباعدة. يمكن بهذه الأداة الحصول بنظرة على معلومات عن حالة خادوم قاعدة البيانات، اتصالات العملاء ومتغيّرات الخادوم. كما تمكّنك من إدارة المستخدمين وصلاحيّاتهم، تصدير البيانات واستيرادها، تنفيذ الاستعلامات Queries، إنشاء مخطّطات Schemas جديدة وغيرها من المهامّ.
</p>

<p>
	يتيح MySQL Workbench أيضًا إمكانيّة تهجير Migrate البيانات من أنظمة إدارة قواعد بيانات أخرى، مثل Microsoft SQL Server و<a href="https://academy.hsoub.com/devops/servers/databases/postgresql/" rel="">PostreSQL</a> إلى MySQL بسهولة ويُسر.
</p>

<p>
	سنبيّن في هذا الدرس كيفية تثبيت الأداة على حاسوبك الشخصي وخطوات ينبغي تطبيقها جهةَ خواديم قواعد البيانات للسماح للأداة بالاتصال بهذه الخواديم. سنأخذ مثالا لتثبيت MySQL Workbench على حاسوب شخصي يعمل بالإصدار 17.04 من أوبونتو وجعله يتّصل بقاعدة بيانات على خادوم يعمل بأوبونتو 16.04. تنطبق نفس الخطوات على بقيّة توزيعات <a href="https://academy.hsoub.com/devops/linux/" rel="">لينكس</a> مع اختلافات تمليها طبيعة مدير الحزم الخاص بالتوزيعة.
</p>

<h2 id="تثبيت-mysql-workbench">
	تثبيت MySQL Workbench
</h2>

<p>
	يمكن الحصول على الأداة MySQL Workbench من صفحة التنزيل على موقع الأداة. اختر صيغة الحزمة والمعماريّة المناسبتَيْن (حزمة <code>deb.</code> ومعماريّة 64 بت بالنسبة لنا) ثم اطلُب تنزيل الملف (قد تحتاج لتسجيل الدخول إلى حساب أوراكل أو إنشاء حساب جديد إن لم يكن لديك واحد، الحساب والأداة مجانيّان).
</p>

<p>
	انتقل بعد اكتمال التنزيل إلى المُجلَّد حيثُ نزّلت الأداة (المجلّد <code>Downloads</code> بالنسبة لنا):
</p>

<pre class="ipsCode" id="ips_uid_3896_7">
cd ~/Downloads
</pre>

<p>
	ثم استخدم الأمر <code>dpkg</code> لتثبيت حزمة الأداة:
</p>

<pre class="ipsCode" id="ips_uid_3896_7">
<code class="hljs lasso"><span class="pln">sudo dpkg </span><span class="hljs-attribute"><span class="pun">-</span><span class="pln">i</span></span><span class="pln"> mysql</span><span class="hljs-attribute"><span class="pun">-</span><span class="pln">workbench</span></span><span class="hljs-attribute"><span class="pun">-</span><span class="pln">community</span></span><span class="hljs-subst"><span class="pun">-*</span></span><span class="hljs-built_in"><span class="pun">.</span></span><span class="pln">deb</span></code></pre>

<p>
	قد تظهر رسائل خطأ تفيد بغياب حزم تعتمد عليها الأداة MySQL Workbench (رسائل الخطأ <code>dependency problems</code>). يمكن حلّ هذه المشاكل بتنفيذ الأمر التالي لتثبيت الحزم المفقودة:
</p>

<pre class="ipsCode" id="ips_uid_3896_7">
<code class="hljs bash"><span class="hljs-built_in"><span class="pln">sudo</span></span><span class="pln"> apt</span><span class="pun">-</span><span class="kwd">get</span><span class="pln"> install </span><span class="hljs-operator"><span class="pun">-</span><span class="pln">f</span></span></code></pre>

<p>
	يحلّ الأمر السابق بتثبيت الحزم التي تطلبها الأداة MySQL Workbench.
</p>

<p>
	نحن الآن جاهزون لتشغيل الأداة MySQL Workbench على الحاسوب الشخصي (العميل)، ولكن قبل ذلك سنضبُط خادوم قاعدة البيانات للسماح للاتصالات البعيدة (أي التي تأتي من عملاء لا يتواجدون مع خادوم قاعدة البيانات على نفس الجهاز).
</p>

<h2 id="إعداد-خادوم-mysql-للاتصالات-البعيدة">
	إعداد خادوم MySQL للاتصالات البعيدة
</h2>

<p>
	إن لم تضبُط خادوم MySQL لقبول اتصالات بعيدة فإن MySQL Workbench لن يمكنه الاتصال بقواعد البيانات الموجودة على هذا الخاودم.
</p>

<p>
	يجب أولا ضبط MySQL لقبول اتصالات قادمة من عناوين غير العنوان المحلّي <code>127.0.0.1</code>. سجّل الدخول إلى الخادوم - مثلا عبر <a href="https://academy.hsoub.com/tags/%D9%85%D8%AF%D8%AE%D9%84%20%D8%A5%D9%84%D9%89%20ssh/" rel=""><abbr title="Secure Shell | القشرة (أو الصَدَفة) الآمنة">SSH</abbr></a> - ثم افتح الملف التالي لتحريره:
</p>

<pre class="ipsCode" id="ips_uid_3896_7">
<code class="hljs avrasm"><span class="pln">sudo nano </span><span class="pun">/</span><span class="pln">etc</span><span class="pun">/</span><span class="pln">mysql</span><span class="pun">/</span><span class="pln">mysql</span><span class="hljs-preprocessor"><span class="pun">.</span><span class="pln">conf</span></span><span class="hljs-preprocessor"><span class="pun">.</span><span class="pln">d</span></span><span class="pun">/</span><span class="pln">mysqld</span><span class="hljs-preprocessor"><span class="pun">.</span><span class="pln">cnf</span></span></code></pre>

<p>
	ابحث عن السطر التالي:
</p>

<pre class="ipsCode" id="ips_uid_3896_7">
<code class="hljs bash"><span class="hljs-built_in"><span class="pln">bind</span></span><span class="pun">-</span><span class="pln">address </span><span class="hljs-number"><span class="lit">127.0</span></span><span class="pun">.</span><span class="hljs-number"><span class="lit">0.1</span></span></code></pre>

<p>
	وعدّله ليصبح:
</p>

<pre class="ipsCode" id="ips_uid_3896_7">
<code class="hljs bash"><span class="hljs-built_in"><span class="pln">bind</span></span><span class="pun">-</span><span class="pln">address </span><span class="hljs-number"><span class="lit">0.0</span></span><span class="pun">.</span><span class="hljs-number"><span class="lit">0.0</span></span></code></pre>

<p>
	احفظ الملف ثم أغلقه.
</p>

<p>
	أعد تشغيل خادوم MySQL بالأمر التالي:
</p>

<pre class="ipsCode" id="ips_uid_3896_7">
<code class="hljs bash"><span class="hljs-built_in"><span class="pln">sudo</span></span><span class="pln"> systemctl restart mysql</span><span class="pun">.</span><span class="pln">service</span></code></pre>

<p>
	خادوم قاعدة البيانات جاهز الآن لتلقّي الاتصالات.
</p>

<p>
	الخطوة الموالية هي تحديد المستخدمين المسموح لهم بالاتصال بخادوم قاعدة البيانات ومن أي عنوان يمكنهم ذلك. يُضبَط هذا الإعداد من محثّ الأوامر command prompt في MySQL.
</p>

<p>
	ننفّذ الأمر التالي للانتقال إلى محثّ أوامر MySQL:
</p>

<pre class="ipsCode" id="ips_uid_3896_7">
<code class="hljs lasso"><span class="pln">mysql </span><span class="hljs-attribute"><span class="pun">-</span><span class="pln">u</span></span><span class="pln"> root </span><span class="hljs-attribute"><span class="pun">-</span><span class="pln">p</span></span></code></pre>

<p>
	<strong>ملحوظة:</strong> أبدل <code>root</code> باسم الحساب الإداري لديك خادوم في قاعدة البيانات.
</p>

<p>
	أدخل كلمة السّر عندما تُطلَب منك، ستجد بعدها أنك أمام سطر أوامر خاص بـMySQL. سنحتاج لتنفيذ أمر يعطي حساب المدير القدرة على الاتصال بخادوم قاعدة البيانات عن بعد (عبر MySQL Workbench).
</p>

<p>
	سنفترض أن عنوان الجهاز الذي ثبّتنا عليه MySQL Workbench هو <code>192.168.1.139</code> وأننا نريد السماح للمسخدم <code>root</code> بالاتصال بجميع قواعد البيانات الموجودة على الخادوم انطلاقا من العنوان السابق. ننفّذ الأمر التالي للحصول على النتيجة المذكورة:
</p>

<pre class="ipsCode" id="ips_uid_3896_7">
<code class="hljs sql"><span class="hljs-operator"><span class="hljs-keyword"><span class="pln">GRANT</span></span><span class="pln"> </span><span class="hljs-keyword"><span class="pln">ALL</span></span><span class="pln"> </span><span class="hljs-keyword"><span class="pln">ON</span></span><span class="pln"> </span><span class="pun">*.*</span><span class="pln"> </span><span class="hljs-keyword"><span class="pln">TO</span></span><span class="pln"> </span><span class="hljs-string"><span class="str">'root'</span></span><span class="pun">@</span><span class="hljs-string"><span class="str">'192.168.1.139'</span></span><span class="pln"> IDENTIFIED </span><span class="hljs-keyword"><span class="pln">BY</span></span><span class="pln"> </span><span class="hljs-string"><span class="str">'PASSWORD'</span></span><span class="pln"> </span><span class="hljs-keyword"><span class="pln">WITH</span></span><span class="pln"> </span><span class="hljs-keyword"><span class="pln">GRANT</span></span><span class="pln"> </span><span class="hljs-keyword"><span class="pln">OPTION</span></span><span class="pun">;</span></span></code></pre>

<p>
	حيث <code>PASSWORD</code> كلمة سرّ المستخدم <code>root</code> (أو أي مستخدم آخر تريد إعطاءه ميزة الاتصال عن بعد بالقاعدة). تأكّد من أن الأمر نُفِّذ دون أخطاء.
</p>

<p>
	نفّذ الأمر:
</p>

<pre class="ipsCode" id="ips_uid_3896_7">
<code class="hljs bash"><span class="hljs-keyword"><span class="kwd">exit</span></span><span class="pun">;</span></code></pre>

<p>
	للخروج من سطر أوامر MySQL.
</p>

<p>
	يمكنك الآن الاتصال بخادوم MySQL انطلاقا من MySQL Workbench.
</p>

<h2 id="الاتصال-بقاعدة-البيانات-من-mysql-workbench">
	الاتصال بقاعدة البيانات من MySQL Workbench
</h2>

<p>
	شغّل التطبيق MySQL Workbench ثم توجّه إلى القائمة <code>Database</code>واختر <code>Connect to database</code>. تظهر النافذة التالية.
</p>

<p style="text-align: center;">
	<img class="ipsImage ipsImage_thumbnailed" data-fileid="23877" data-unique="6d0ra3qje" src="https://academy.hsoub.com/uploads/monthly_2017_07/01_Workbench_connect_db.jpg.398df5bfc0a6e9d448683b394886b65c.jpg" alt="01_Workbench_connect_db.jpg"></p>

<p>
	نحدّد في هذه النافذة تفاصيل الاتصال: عنوان الخادوم، المنفذ (مبدئيّا <code>3306</code>) واسم المستخدم ثم اضغط على الزرّ <code>OK</code>. سيُطلب منك إدخال كلمة سر المستخدم.
</p>

<p>
	تظهر بعد إدخال كلمة السر الصحيحة النافذة التاليّة التي يمكن من خلالها تنفيذ إجراءات مختلفة على قاعدة البيانات.
</p>

<p style="text-align: center;">
	<img class="ipsImage ipsImage_thumbnailed" data-fileid="23878" data-unique="997cogqya" src="https://academy.hsoub.com/uploads/monthly_2017_07/02_Workbench_connect_db.jpg.37097b03d9de6e0085ca310546c44268.jpg" alt="02_Workbench_connect_db.jpg"></p>

<p>
	تُستخدَم الطريقة السابقة لإنشاء اتصال واحد. إن كنت تعرف أنك ستتصّل بهذا الخادوم مرارا فالأفضل أن تختار <code>Manage Connections</code> من القائمة <code>Database</code>. تظهر النافذة التالية.
</p>

<p style="text-align: center;">
	<img class="ipsImage ipsImage_thumbnailed" data-fileid="23879" data-unique="jzvkywkxa" src="https://academy.hsoub.com/uploads/monthly_2017_07/03_manage_connections.jpg.d238bf8f34216f09d0293d3c3580b9fd.jpg" alt="03_manage_connections.jpg"></p>

<p>
	انقر على الزّر <code>New</code>، حدّد التفاصيل المطلوبة للاتصال بقاعدة البيانات. تأكّد من إعطاء اسم للاتصال (خانة <code>Connection name</code>) ثم انقر على زرّ <code>Test Connection</code> لاختبار الاتصال. أدخل كلمة السر عندما تُطلَب منك ثم انقر على الزرّ <code>OK</code>. انقر على الزرّ <code>OK</code> مرة أخرى بعد نجاح اختبار الاتصال ثم <code>Close</code> لإغلاق نافذة الاختبار.
</p>

<p>
	سيُحفَظ الاتصال بعد إغلاق نافذة الاختبار. يمكنك بعدها الذهاب إلى القائمة <code>Database</code> واختيار <code>Connect to Database</code> ثم تحديد الخادوم الذي تريد الاتصال به من القائمة المنسدلة <code>Stored Connection</code>
</p>

<p style="text-align: center;">
	<img class="ipsImage ipsImage_thumbnailed" data-fileid="23880" data-unique="gv8od2vfo" src="https://academy.hsoub.com/uploads/monthly_2017_07/04_stored_connection.jpg.a05553f63a3e666d880de26831f319ac.jpg" alt="04_stored_connection.jpg"></p>

<p>
	يمكنك بالوصول إلى هذه النقطة البدء في إنشاء قواعد البيانات وإدارتها بمساعدة أداة رسوميّة فعّالة وصديقة للمستخدم.
</p>

<p>
	ليس MySQL Workbench سوى أداة من بين أدوات رسومية كثيرة تساعد في جعل إدارتك لقواعد بيانات MySQL أكثر فاعليّة، جرّبها وستجد أنها ستصبح وسيلتك اليومية لإدارة قواعد بيانات MySQL.
</p>

<p>
	ترجمة - بتصرّف - للمقال <a href="https://www.linux.com/learn/intro-to-linux/2017/4/how-install-and-use-mysql-workbench-your-database-gui" rel="external nofollow">How to Install and Use MySQL Workbench As Your Database GUI</a> لصاحبه Jack Wallen.
</p>
]]></description><guid isPermaLink="false">324</guid><pubDate>Mon, 03 Jul 2017 07:06:00 +0000</pubDate></item><item><title>&#x643;&#x64A;&#x641; &#x62A;&#x62D;&#x633;&#x651;&#x646; &#x627;&#x644;&#x627;&#x633;&#x62A;&#x639;&#x644;&#x627;&#x645;&#x627;&#x62A; &#x648;&#x627;&#x644;&#x62C;&#x62F;&#x627;&#x648;&#x644; &#x641;&#x64A; &#x642;&#x627;&#x639;&#x62F;&#x629; &#x628;&#x64A;&#x627;&#x646;&#x627;&#x62A; MySQL</title><link>https://academy.hsoub.com/devops/servers/databases/mysql/%D9%83%D9%8A%D9%81-%D8%AA%D8%AD%D8%B3%D9%91%D9%86-%D8%A7%D9%84%D8%A7%D8%B3%D8%AA%D8%B9%D9%84%D8%A7%D9%85%D8%A7%D8%AA-%D9%88%D8%A7%D9%84%D8%AC%D8%AF%D8%A7%D9%88%D9%84-%D9%81%D9%8A-%D9%82%D8%A7%D8%B9%D8%AF%D8%A9-%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-mysql-r313/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2017_05/Untitled-3.png.41db7ac9904bb4c8dea89aa60cdec5d3.png" /></p>

<p>
	ينتشر استخدام MySQL وMariaDB كثيرا لإدارة قواعد البيانات العلاقيّة، وتستخدم الاثنتان استعلامات SQL لإدخال البيانات في القاعدة واستخراجها منها.
</p>

<p>
	على الرغم من أنّ استعلامات SQL في مجملها أوامر سهلة يمكن تعلّمها بيُسر، إلا أن الاستعلامات ودوالّ قواعد البيانات لا تعمل بنفس الكفاءة. تصبح كفاءة استعلامات SQL أكثر أهميّة مع ازدياد كميّة البيانات التي تخزّنها؛ وازدياد شعبيّة موقعك، في حال كنت تستخدم قاعدة البيانات في موقع ويب.
</p>

<p style="text-align: center;">
	<img alt="Untitled-3.png" class="ipsImage ipsImage_thumbnailed" data-fileid="23102" data-unique="v1nhsuzrn" src="https://academy.hsoub.com/uploads/monthly_2017_05/Untitled-3.png.6120b0e7ceb783e86f22f9f986841854.png"></p>

<p>
	يناقش هذا الدليل إجراءات بسيطة تمكّن من تسريع تنفيذ الاستعلامات في MySQL وMariaDB. سنفترض أنّ لديك قاعدة بيانات MySQL أو MariaDB مثبّتة على خادومك.
</p>

<h2 id="مبادئ-عامة-في-تهيئة-الجداول-tables">
	مبادئ عامّة في تهيئة الجداول Tables
</h2>

<p>
	تبدأ فعاليّة قاعدة البيانات بتصميم بنية جداول تحترم معايير مجرَّبة لتحسين الأداء. يعني هذا أنه يجب عليك التفكير في أفضل طريقة لتنظيم بياناتك قبل البدء في استخدام البرنامج.
</p>

<p>
	في ما يلي بضعة أسئلة تساعدك في إيجاد طريقة مثلى لتهيئة مخطّط الجداول في قاعدة البيانات.
</p>

<h3 id="ما-هو-الاستخدام-الأساسي-للجدول">
	ما هو الاستخدام الأساسي للجدول؟
</h3>

<p>
	تُملي معرفةُ الكيفية التي ستُستغَل بها البيانات الموجودة في الجدول مستقبلا أفضلَ مقاربة لتخطيط الجداول في قاعدة البيانات.
</p>

<p>
	إذا كانت بعض البيانات ستُحدَّث باستمرار فإن الأفضل غالبا هو وضعها في جدول خاصّ بها. يوجد في برامج إدارة قواعد البيانات تخبئة Cache داخليّة تُحدَّث ويُعاد بناءها مع كل تغيير على الجدول، فإن كانت البيانات المُحدَّثة في جدول مستقل فإن البرنامج لن يُضطر لتحديث بقيّة البيانات في كلّ مرة وهو ما يعني جهدا أقل ووصولا أسرع.
</p>

<p>
	تكون عمليّات التحديث عموما أسرع بكثير عند تنفيذها على جداول صغيرة، بينما يُفضَّّل تنفيذ تحليل البيانات المعقّدة على الجداول الكبيرة، بدلا من تجميع الكثير من الجداول الصغيرة، عبر تعليمات <code>join</code> مثلا.
</p>

<h3 id="ما-هي-أنواع-البيانات-المطلوبة">
	ما هي أنواع البيانات المطلوبة؟
</h3>

<p>
	يُمكن أحيانا اقتصاد الكثير من الوقت على المدى الطويل إن استطعت تطبيق قيود سلفا على أحجام البيانات المطلوبة.
</p>

<p>
	إن كانت لديك، على سبيل المثال، قيم محدودة لأحد الحقول النصيّة فيمكنك استخدام نوع البيانات <code>enum</code> لهذا الحقل بدلا من <code>varchar</code>. البيانات من النوع البيانات <code>enum</code> ذات حجم صغير وبالتالي يُنفَّذ الاستعلام عنها بسرعة كبيرة. يصلُح النوع <code>enum</code> - مثلا - لحقل يُخزّن أدوار المستخدِمين في منتدى: مدير Admin، مشرف Moderator، مستخدم فعّال Poweruser أو مستخدم عادي User.
</p>

<h3 id="ماهي-الحقول-التي-ستستعلم-عنها">
	ماهي الحقول التي ستستعلِم عنها؟
</h3>

<p>
	تساهم المعرفة القبْليّة للحقول التي ستبحث عن قيمها باستمرار في التحسين المعتبر لسرعة تنفيذ الاستعلامات، وذلك بفهرسة Indexing حقول البحث.
</p>

<p>
	يُضاف الفهرس على حقل على النحو التالي عند إنشاء الجدول:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_1413_9" style="">
<span class="pln">CREATE TABLE example_table </span><span class="pun">(</span><span class="pln">
    id INTEGER NOT NULL AUTO_INCREMENT</span><span class="pun">,</span><span class="pln">
    name VARCHAR</span><span class="pun">(</span><span class="lit">50</span><span class="pun">),</span><span class="pln">
    address VARCHAR</span><span class="pun">(</span><span class="lit">150</span><span class="pun">),</span><span class="pln">
    username VARCHAR</span><span class="pun">(</span><span class="lit">16</span><span class="pun">),</span><span class="pln">
    PRIMARY KEY </span><span class="pun">(</span><span class="pln">id</span><span class="pun">),</span><span class="pln">
    INDEX </span><span class="pun">(</span><span class="pln">username</span><span class="pun">)</span><span class="pln">
</span><span class="pun">);</span></pre>

<p>
	لاحظ التعليمة <code>INDEX</code> أعلاه.
</p>

<p>
	يفيد الفهرس على الحقل <code>username</code> كثيرا إذا كنا نعرف أن زوّار موقعنا سيبحثون عن المستخدمين بأسماء حساباتهم. يُنشئ الاستعلام أعلاه جدول <code>example_table</code> يمكن عرض خاصيّاته كالتالي:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_1413_9" style="">
<code class="hljs "><span class="pln">explain example_table</span><span class="pun">;</span></code></pre>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_1413_9" style="">
<code class="hljs vhdl"><span class="pun">+</span><span class="hljs-comment"><span class="pun">----------+--------------+------+-----+---------+----------------+</span></span><span class="pln">
</span><span class="pun">|</span><span class="pln"> </span><span class="typ">Field</span><span class="pln">    </span><span class="pun">|</span><span class="pln"> </span><span class="hljs-keyword"><span class="typ">Type</span></span><span class="pln">         </span><span class="pun">|</span><span class="pln"> </span><span class="hljs-keyword"><span class="typ">Null</span></span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="typ">Key</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="hljs-keyword"><span class="typ">Default</span></span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="typ">Extra</span><span class="pln">          </span><span class="pun">|</span><span class="pln">
</span><span class="pun">+</span><span class="hljs-comment"><span class="pun">----------+--------------+------+-----+---------+----------------+</span></span><span class="pln">
</span><span class="pun">|</span><span class="pln"> id       </span><span class="pun">|</span><span class="pln"> </span><span class="kwd">int</span><span class="pun">(</span><span class="hljs-number"><span class="lit">11</span></span><span class="pun">)</span><span class="pln">      </span><span class="pun">|</span><span class="pln"> NO   </span><span class="pun">|</span><span class="pln"> PRI </span><span class="pun">|</span><span class="pln"> </span><span class="hljs-keyword"><span class="pln">NULL</span></span><span class="pln">    </span><span class="pun">|</span><span class="pln"> auto_increment </span><span class="pun">|</span><span class="pln">
</span><span class="pun">|</span><span class="pln"> name     </span><span class="pun">|</span><span class="pln"> varchar</span><span class="pun">(</span><span class="hljs-number"><span class="lit">50</span></span><span class="pun">)</span><span class="pln">  </span><span class="pun">|</span><span class="pln"> YES  </span><span class="pun">|</span><span class="pln">     </span><span class="pun">|</span><span class="pln"> </span><span class="hljs-keyword"><span class="pln">NULL</span></span><span class="pln">    </span><span class="pun">|</span><span class="pln">                </span><span class="pun">|</span><span class="pln">
</span><span class="pun">|</span><span class="pln"> address  </span><span class="pun">|</span><span class="pln"> varchar</span><span class="pun">(</span><span class="hljs-number"><span class="lit">150</span></span><span class="pun">)</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> YES  </span><span class="pun">|</span><span class="pln">     </span><span class="pun">|</span><span class="pln"> </span><span class="hljs-keyword"><span class="pln">NULL</span></span><span class="pln">    </span><span class="pun">|</span><span class="pln">                </span><span class="pun">|</span><span class="pln">
</span><span class="pun">|</span><span class="pln"> username </span><span class="pun">|</span><span class="pln"> varchar</span><span class="pun">(</span><span class="hljs-number"><span class="lit">16</span></span><span class="pun">)</span><span class="pln">  </span><span class="pun">|</span><span class="pln"> YES  </span><span class="pun">|</span><span class="pln"> MUL </span><span class="pun">|</span><span class="pln"> </span><span class="hljs-keyword"><span class="pln">NULL</span></span><span class="pln">    </span><span class="pun">|</span><span class="pln">                </span><span class="pun">|</span><span class="pln">
</span><span class="pun">+</span><span class="hljs-comment"><span class="pun">----------+--------------+------+-----+---------+----------------+</span></span><span class="pln">
</span><span class="hljs-number"><span class="lit">4</span></span><span class="pln"> rows </span><span class="hljs-keyword"><span class="kwd">in</span></span><span class="pln"> </span><span class="kwd">set</span><span class="pln"> </span><span class="pun">(</span><span class="hljs-number"><span class="lit">0.00</span></span><span class="pln"> sec</span><span class="pun">)</span></code></pre>

<p>
	يوجد لدينا - كما يظهر - فهرسان. الأول المفتاح الرئيس Primary key ويوجد على حقل المعرِّف <code>id</code>، أما الثاني فهو الذي عرّفناه ويوجد على الحقل <code>username</code>. يعني هذا أن البحث عن المستخدمين بأسماء حساباتهم سيكون أسرع كثيرا من البحث عنهم بأحد الحقول المتبقيّة.
</p>

<p>
	من المهمّ جدا، من وجهة نظر التصميم البرمجي، التفكير في الحقول التي يجب أن تُفهرَس وفعل ذلك مع إنشاء الجدول؛ إلا أن بالإمكان ايضا إضافة فهارس إلى جداول موجودة سلفا على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_1413_9" style="">
<code class="hljs sql"><span class="hljs-operator"><span class="hljs-keyword"><span class="pln">CREATE</span></span><span class="pln"> INDEX index_name </span><span class="hljs-keyword"><span class="pln">ON</span></span><span class="pln"> table_name</span><span class="pun">(</span><span class="pln">column_name</span><span class="pun">);</span></span></code></pre>

<p>
	توجد طريقة أخرى للحصول على نفس النتيجة:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_1413_9" style="">
<code class="hljs sql"><span class="hljs-operator"><span class="hljs-keyword"><span class="pln">ALTER</span></span><span class="pln"> </span><span class="hljs-keyword"><span class="pln">TABLE</span></span><span class="pln"> table_name </span><span class="hljs-keyword"><span class="pln">ADD</span></span><span class="pln"> INDEX </span><span class="pun">(</span><span class="pln"> column_name </span><span class="pun">);</span></span></code></pre>

<h3 id="استخدام-الدالة-explain-لإيجاد-حقول-لفهرستها">
	استخدام الدالة explain لإيجاد حقول لفهرستها
</h3>

<p>
	إذا كان برنامجك يطلب تنفيذ استعلامات منتظمة يمكن التنبؤ بها فيجب عليك تحليل هذه الاستعلامات للتأكد من أن الاستعلامات تستخدم حقولا بها فهارس كلما كان ذلك ممكنا. تساعد الدالة <code>explain</code> في هذه المهمة.
</p>

<p>
	سنستورد قاعدة البيانات التجريبية الموجودة في المرفق <a class="ipsAttachLink" data-fileid="23100" href="https://academy.hsoub.com/applications/core/interface/file/attachment.php?id=23100" rel="">employees_db.zip</a> لتطبيق بعض الأمثلة عليها. نزّل الملف المضغوط ثم نفّذ الأمرين التاليين لفكّ ضغطه والانتقال إلى المجلّد <code>employees_db</code> الناتج عن فك الضغط:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_1413_9" style="">
<code class="hljs avrasm"><span class="pln">tar xjvf employees_db</span><span class="pun">-</span><span class="pln">full</span><span class="pun">-</span><span class="hljs-number"><span class="lit">1.0</span></span><span class="hljs-number"><span class="pun">.</span><span class="lit">6</span></span><span class="hljs-preprocessor"><span class="lit">.tar</span></span><span class="hljs-preprocessor"><span class="pun">.</span><span class="pln">bz</span></span><span class="pln">2
cd employees_db</span></code></pre>

<p>
	ثم ننفّذ اﻷمر التالي لاستيراد القاعدة إلى MySQL (ينبغي أن يكون عميل MySQL - حزمة <code>mysql-client</code> - مثبتا لديك):
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_1413_9" style="">
<code class="hljs lasso"><span class="pln">mysql </span><span class="hljs-attribute"><span class="pun">-</span><span class="pln">u</span></span><span class="pln"> root </span><span class="hljs-attribute"><span class="pun">-</span><span class="pln">p</span></span><span class="pln"> </span><span class="hljs-attribute"><span class="pun">-</span><span class="pln">t</span></span><span class="pln"> </span><span class="hljs-subst"><span class="pun">&lt;</span></span><span class="pln"> employees</span><span class="hljs-built_in"><span class="pun">.</span></span><span class="pln">sql</span></code></pre>

<p>
	ستُطلب منك كلمة سرّ خادوم MySQL.
</p>

<p>
	نسجّل الدخول إلى خادوم MySQL:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_1413_9" style="">
<code class="hljs lasso"><span class="pln">mysql </span><span class="hljs-attribute"><span class="pun">-</span><span class="pln">u</span></span><span class="pln"> root </span><span class="hljs-attribute"><span class="pun">-</span><span class="pln">p</span></span></code></pre>

<p>
	ننفّذ الأمر التالي داخل المحثّ Prompt الخاص بـMySQL لتحديد قاعدة البيانات التي استوردناها للتو:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_1413_9" style="">
<code class="hljs php"><span class="hljs-keyword"><span class="kwd">use</span></span><span class="pln"> </span><span class="hljs-title"><span class="pln">employees</span></span><span class="pun">;</span></code></pre>

<p>
	نحتاج أولا لإخبار MySQL ألا يستخدم تخبئته الداخليّة ليمكننا الحكم بدقّة على الوقت اللازم لتنفيذ هذه المهامّ.
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_1413_9" style="">
<code class="hljs asciidoc"><span class="pln">SET GLOBAL query</span><span class="hljs-emphasis"><span class="pln">_cache_</span></span><span class="pln">size </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
SHOW VARIABLES LIKE </span><span class="str">"query</span><span class="hljs-emphasis"><span class="str">_cache_</span></span><span class="str">size"</span><span class="pun">;</span><span class="pln">

</span><span class="hljs-code"><span class="pun">+------------------+</span></span><span class="pun">-------+</span><span class="pln">
</span><span class="hljs-header"><span class="pun">|</span><span class="pln"> </span><span class="typ">Variable_name</span><span class="pln">    </span><span class="pun">|</span><span class="pln"> </span><span class="typ">Value</span><span class="pln"> </span><span class="pun">|</span><span class="pln">
</span><span class="pun">+------------------+-------+</span></span><span class="pln">
</span><span class="hljs-header"><span class="pun">|</span><span class="pln"> query_cache_size </span><span class="pun">|</span><span class="pln"> </span><span class="lit">0</span><span class="pln">     </span><span class="pun">|</span><span class="pln">
</span><span class="pun">+------------------+-------+</span></span><span class="pln">
</span><span class="lit">1</span><span class="pln"> row </span><span class="kwd">in</span><span class="pln"> </span><span class="kwd">set</span><span class="pln"> </span><span class="pun">(</span><span class="lit">0.00</span><span class="pln"> sec</span><span class="pun">)</span></code></pre>

<p>
	يمكننا الآن تشغيل استعلام بسيط على مجموعة كبيرة من البيانات:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_1413_9" style="">
<code class="hljs asciidoc"><span class="pln">SELECT COUNT</span><span class="pun">(</span><span class="hljs-strong"><span class="pun">*)</span><span class="pln"> FROM salaries WHERE salary BETWEEN </span><span class="lit">60000</span><span class="pln"> AND </span><span class="lit">70000</span><span class="pun">;</span><span class="pln">

</span></span><span class="hljs-code"><span class="pun">+----------+</span></span><span class="pln">
</span><span class="hljs-header"><span class="pun">|</span><span class="pln"> count</span><span class="pun">(*)</span><span class="pln"> </span><span class="pun">|</span><span class="pln">
</span><span class="pun">+----------+</span></span><span class="pln">
</span><span class="hljs-header"><span class="pun">|</span><span class="pln">   </span><span class="lit">588322</span><span class="pln"> </span><span class="pun">|</span><span class="pln">
</span><span class="pun">+----------+</span></span><span class="pln">
</span><span class="lit">1</span><span class="pln"> row </span><span class="kwd">in</span><span class="pln"> </span><span class="kwd">set</span><span class="pln"> </span><span class="pun">(</span><span class="lit">0.80</span><span class="pln"> sec</span><span class="pun">)</span></code></pre>

<p>
	يطلُب الاستعلام أعلاه عدَّ الموظفين ذوي الدخل المحصور بين <code>60000</code> و<code>70000</code>. تُظهر النتيجة وجود <code>588322</code> موظف في هذا المجال.
</p>

<p>
	نستفيد الآن من الدالة <code>explain</code> لرؤية كيف نُفِّذ الاستعلام السابق وذلك بإضافة الكلمة <code>EXPLAIN</code> أمام الاستعلام الذي طبّقناه للتو:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_1413_9" style="">
<code class="hljs asciidoc"><span class="pln">EXPLAIN SELECT COUNT</span><span class="pun">(</span><span class="hljs-strong"><span class="pun">*)</span><span class="pln"> FROM salaries WHERE salary BETWEEN </span><span class="lit">60000</span><span class="pln"> AND </span><span class="lit">70000</span><span class="pun">;</span><span class="pln">

</span></span><span class="hljs-code"><span class="pun">+----+</span></span><span class="pun">-------------</span><span class="hljs-code"><span class="pun">+----------+</span></span><span class="pun">------</span><span class="hljs-code"><span class="pun">+---------------+</span></span><span class="pun">------</span><span class="hljs-code"><span class="pun">+---------+</span></span><span class="pun">------</span><span class="hljs-code"><span class="pun">+---------+</span></span><span class="pun">-------------+</span><span class="pln">
</span><span class="hljs-header"><span class="pun">|</span><span class="pln"> id </span><span class="pun">|</span><span class="pln"> select_type </span><span class="pun">|</span><span class="pln"> table    </span><span class="pun">|</span><span class="pln"> type </span><span class="pun">|</span><span class="pln"> possible_keys </span><span class="pun">|</span><span class="pln"> key  </span><span class="pun">|</span><span class="pln"> key_len </span><span class="pun">|</span><span class="pln"> </span><span class="kwd">ref</span><span class="pln">  </span><span class="pun">|</span><span class="pln"> rows    </span><span class="pun">|</span><span class="pln"> </span><span class="typ">Extra</span><span class="pln">       </span><span class="pun">|</span><span class="pln">
</span><span class="pun">+----+-------------+----------+------+---------------+------+---------+------+---------+-------------+</span></span><span class="pln">
</span><span class="hljs-header"><span class="pun">|</span><span class="pln">  </span><span class="lit">1</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> SIMPLE      </span><span class="pun">|</span><span class="pln"> salaries </span><span class="pun">|</span><span class="pln"> ALL  </span><span class="pun">|</span><span class="pln"> NULL          </span><span class="pun">|</span><span class="pln"> NULL </span><span class="pun">|</span><span class="pln"> NULL    </span><span class="pun">|</span><span class="pln"> NULL </span><span class="pun">|</span><span class="pln"> </span><span class="lit">2844738</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="typ">Using</span><span class="pln"> </span><span class="kwd">where</span><span class="pln"> </span><span class="pun">|</span><span class="pln">
</span><span class="pun">+----+-------------+----------+------+---------------+------+---------+------+---------+-------------+</span></span><span class="pln">
</span><span class="lit">1</span><span class="pln"> row </span><span class="kwd">in</span><span class="pln"> </span><span class="kwd">set</span><span class="pln"> </span><span class="pun">(</span><span class="lit">0.00</span><span class="pln"> sec</span><span class="pun">)</span></code></pre>

<p>
	يظهر في نتيجة استخدام التعليمة <code>EXPLAIN</code> أن قيمة الحقل <code>key</code> هي <code>NULL</code>، ما يعني أنه لم يُستخدَم أي فهرس في الاستعلام السابق.
</p>

<p>
	فلنضف فهرسا على الحقل <code>salary</code>، ثم لنعد نفس الاستعلام ولننظر إن كان ذلك يُسرّع من تنفيذه:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_1413_9" style="">
<code class="hljs sql"><span class="hljs-operator"><span class="hljs-keyword"><span class="pln">ALTER</span></span><span class="pln"> </span><span class="hljs-keyword"><span class="pln">TABLE</span></span><span class="pln"> salaries </span><span class="hljs-keyword"><span class="pln">ADD</span></span><span class="pln"> INDEX </span><span class="pun">(</span><span class="pln"> salary </span><span class="pun">);</span></span><span class="pln">
</span><span class="hljs-operator"><span class="hljs-keyword"><span class="pln">SELECT</span></span><span class="pln"> </span><span class="hljs-aggregate"><span class="pln">COUNT</span></span><span class="pun">(*)</span><span class="pln"> </span><span class="hljs-keyword"><span class="pln">FROM</span></span><span class="pln"> salaries </span><span class="hljs-keyword"><span class="pln">WHERE</span></span><span class="pln"> salary BETWEEN </span><span class="hljs-number"><span class="lit">60000</span></span><span class="pln"> </span><span class="hljs-keyword"><span class="pln">AND</span></span><span class="pln"> </span><span class="hljs-number"><span class="lit">70000</span></span><span class="pun">;</span></span></code></pre>

<p>
	النتيجة:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_1413_9" style="">
<code class="hljs asciidoc"><span class="hljs-code"><span class="pun">+----------+</span></span><span class="pln">
</span><span class="hljs-header"><span class="pun">|</span><span class="pln"> count</span><span class="pun">(*)</span><span class="pln"> </span><span class="pun">|</span><span class="pln">
</span><span class="pun">+----------+</span></span><span class="pln">
</span><span class="hljs-header"><span class="pun">|</span><span class="pln">   </span><span class="lit">588322</span><span class="pln"> </span><span class="pun">|</span><span class="pln">
</span><span class="pun">+----------+</span></span><span class="pln">
</span><span class="lit">1</span><span class="pln"> row </span><span class="kwd">in</span><span class="pln"> </span><span class="kwd">set</span><span class="pln"> </span><span class="pun">(</span><span class="lit">0.14</span><span class="pln"> sec</span><span class="pun">)</span></code></pre>

<p>
	يمكن ملاحظة أن سرعة تنفيذ الاستعلام تحسّنت كثيرا من <code>0.80</code> ثانية قبل إضافة الفهرس إلى <code>0.14</code>بعد إضافته.
</p>

<p>
	قاعدة مهمّة أخرى عند استخدام الفهارس هي أنه ينبغي الانتباه إلى ربط الجداول (عبر التعليمة <code>join</code> مثلا)؛ إذ يجب أن تُنشَأ فهارس للحقول المستخدمة في الربط، كما يجب أن تشترك هذه الحقول في نوع البيانات.
</p>

<p>
	على سبيل المثال، إن كان لديك جدول يحوي وصفات طعام (وليكن اسمه <code>cheeses</code>) وآخر لمكوّنات كلّ وصفة (وليكن اسمُه <code>ingredients</code>) فإن ربط الجدوليْن يمكن أن يكون حسب حقل من النوع <code>INT</code> (عدد طبيعي) يحوي معرّف المكوّن (وليكن اسمُه <code>ingredient_id</code>) موجود في الجدوليْن. يمكننا بعدها إنشاء فهرس على كل من الحقليْن <code>ingredient_id</code> وبالتالي تسريع استعلامات <code>join</code> كثيرا.
</p>

<h2 id="تحسين-الاستعلامات-لتسريع-تنفيذها">
	تحسين الاستعلامات لتسريع تنفيذها
</h2>

<p>
	يتعلّق الجزء الثاني من معادلة تسريع الاستعلامات بتحسين الاستعلامات نفسها. تتطلّب بعض التعليمات قدرات حسابية أعلى من تعليمات أخرى، كما يمكن في أحيان كثيرة الحصول على نفس النتيجة بأكثر من طريقة، مع اختلاف في الكلفة الحسابية لكلّ طريقة.
</p>

<p>
	يمكن ألا تحتاج إلا إلى نتائج قليلة العدد، حسب الغرض الذي ستستخدم فيه نتيجة الاستعلام. إذا أردت على سبيل المثال معرفة ما إذا كان هناك موظَّف بدخل أقل من <code>40000</code> في قاعدة البيانات التي نزّلناها سابقا، فالاستعلام التالي يجيبك:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_1413_9" style="">
<code class="hljs sql"><span class="hljs-operator"><span class="hljs-keyword"><span class="pln">SELECT</span></span><span class="pln"> </span><span class="pun">*</span><span class="pln"> </span><span class="hljs-keyword"><span class="pln">FROM</span></span><span class="pln"> SALARIES </span><span class="hljs-keyword"><span class="pln">WHERE</span></span><span class="pln"> salary </span><span class="pun">&lt;</span><span class="pln"> </span><span class="hljs-number"><span class="lit">40000</span></span><span class="pln"> LIMIT </span><span class="hljs-number"><span class="lit">1</span></span><span class="pun">;</span></span></code></pre>

<p>
	النتيجة:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_1413_9" style="">
<code class="hljs asciidoc"><span class="hljs-code"><span class="pun">+--------+</span></span><span class="pun">--------</span><span class="hljs-code"><span class="pun">+------------+</span></span><span class="pun">------------+</span><span class="pln">
</span><span class="hljs-header"><span class="pun">|</span><span class="pln"> emp_no </span><span class="pun">|</span><span class="pln"> salary </span><span class="pun">|</span><span class="pln"> from_date  </span><span class="pun">|</span><span class="pln"> to_date    </span><span class="pun">|</span><span class="pln">
</span><span class="pun">+--------+--------+------------+------------+</span></span><span class="pln">
</span><span class="hljs-header"><span class="pun">|</span><span class="pln">  </span><span class="lit">10022</span><span class="pln"> </span><span class="pun">|</span><span class="pln">  </span><span class="lit">39935</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="lit">2000</span><span class="pun">-</span><span class="lit">09</span><span class="pun">-</span><span class="lit">02</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="lit">2001</span><span class="pun">-</span><span class="lit">09</span><span class="pun">-</span><span class="lit">02</span><span class="pln"> </span><span class="pun">|</span><span class="pln">
</span><span class="pun">+--------+--------+------------+------------+</span></span><span class="pln">
</span><span class="lit">1</span><span class="pln"> row </span><span class="kwd">in</span><span class="pln"> </span><span class="kwd">set</span><span class="pln"> </span><span class="pun">(</span><span class="lit">0.00</span><span class="pln"> sec</span><span class="pun">)</span></code></pre>

<p>
	يُنفَّّذ الاستعلام سريعا لأنه يكتفي بأول تسجيلة تحقّق الشرط المطلوب.
</p>

<p>
	إن كان الاستعلام - مثلا - يستخدم عامل المقارنة <code>OR</code> وكان عنصرا المقارنة يختبران <strong>حقولا مختلفة</strong> فإن الاستعلام قد يأخذ وقتا أكثر من اللازم. على سبيل المثال، إن أردت البحث عن جميع الموظفين الذين تبدأ أسماءهم الشخصية والعائلية بـ<code>Bre</code> فستبحث عن قيم حقليْن مختلفيْن (<code>first_name</code> و<code>last_name</code>). يكون الاستعلام باستخدام العامل <code>OR</code> على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_1413_9" style="">
<code class="hljs sql"><span class="hljs-operator"><span class="hljs-keyword"><span class="pln">SELECT</span></span><span class="pln"> </span><span class="pun">*</span><span class="pln"> </span><span class="hljs-keyword"><span class="pln">FROM</span></span><span class="pln"> employees </span><span class="hljs-keyword"><span class="pln">WHERE</span></span><span class="pln"> last_name </span><span class="hljs-keyword"><span class="pln">like</span></span><span class="pln"> </span><span class="hljs-string"><span class="str">'Bre%'</span></span><span class="pln"> </span><span class="hljs-keyword"><span class="pln">OR</span></span><span class="pln"> first_name </span><span class="hljs-keyword"><span class="pln">like</span></span><span class="pln"> </span><span class="hljs-string"><span class="str">'Bre%'</span></span><span class="pun">;</span></span></code></pre>

<p>
	إلا أن الاستعلام <strong><em>قد يكون</em></strong> (حسب طبيعة البيانات في الجدول) أسرع إن بحثتَ عن الأسماء الشخصيّة أولا في استعلام خاصّ ثم عن الأسماء العائلية ثانيا ودمجت الاثنين:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_1413_9" style="">
<code class="hljs sql"><span class="hljs-operator"><span class="hljs-keyword"><span class="pln">SELECT</span></span><span class="pln"> </span><span class="pun">*</span><span class="pln"> </span><span class="hljs-keyword"><span class="pln">FROM</span></span><span class="pln"> employees </span><span class="hljs-keyword"><span class="pln">WHERE</span></span><span class="pln"> first_name </span><span class="hljs-keyword"><span class="pln">like</span></span><span class="pln"> </span><span class="hljs-string"><span class="str">'Bre%'</span></span><span class="pln"> </span><span class="hljs-keyword"><span class="pln">UNION</span></span><span class="pln"> </span><span class="hljs-keyword"><span class="pln">SELECT</span></span><span class="pln"> </span><span class="pun">*</span><span class="pln"> </span><span class="hljs-keyword"><span class="pln">FROM</span></span><span class="pln"> employees </span><span class="hljs-keyword"><span class="pln">WHERE</span></span><span class="pln"> last_name </span><span class="hljs-keyword"><span class="pln">like</span></span><span class="pln"> </span><span class="hljs-string"><span class="str">'Bre%'</span></span><span class="pun">;</span></span></code></pre>

<h3 id="خاتمة">
	خاتمة
</h3>

<p>
	عرضنا في هذا المقال لبضعة حيّل تساعدك في البدء في تحسين الاستعلامات الموجهة لقاعدة بيانات MySQL (أو MariaDB). توجد الكثير من الحيّل الأخرى التي ستساعدك في الرفع من أداء قاعدة البيانات وبالتالي أداء تطبيقك أو موقعك.
</p>

<p>
	يوفّر نظاما إدارة قواعد البيانات MySQL وMariaDB توثيقا جيّدا حول كيفية تحسين استعلاماتك وإعداد قاعدة البيانات لأداء أعلى. يجب أن تتذكّر أن تحسين أداء قاعدة البيانات مرتبط ارتباطا وثيقا بطبيعة استخدامها والبيانات المخزّنة فيها، لذا كلّ ما كانت سيناريوهات الاستخدام أوضح وأكثر انتظاما كلّ ما كان تحسين الاستعلامات أسهل.
</p>

<p>
	ترجمة - بتصرف - للمقال <a href="https://www.digitalocean.com/community/tutorials/how-to-optimize-queries-and-tables-in-mysql-and-mariadb-on-a-vps" rel="external nofollow">How To Optimize Queries and Tables in MySQL and MariaDB on a VPS</a> لصاحبه Justin Ellingwood.
</p>
]]></description><guid isPermaLink="false">313</guid><pubDate>Fri, 05 May 2017 21:03:09 +0000</pubDate></item><item><title>&#x643;&#x64A;&#x641;&#x64A;&#x629; &#x62A;&#x63A;&#x64A;&#x64A;&#x631; &#x645;&#x62C;&#x644;&#x62F; &#x62A;&#x62E;&#x632;&#x64A;&#x646; &#x628;&#x64A;&#x627;&#x646;&#x627;&#x62A; MySQL &#x625;&#x644;&#x649; &#x645;&#x643;&#x627;&#x646;&#x64D; &#x622;&#x62E;&#x631; &#x628;&#x627;&#x633;&#x62A;&#x62E;&#x62F;&#x627;&#x645; &#x627;&#x644;&#x648;&#x635;&#x644;&#x627;&#x62A; &#x627;&#x644;&#x631;&#x645;&#x632;&#x64A;&#x629;</title><link>https://academy.hsoub.com/devops/servers/databases/mysql/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%AA%D8%BA%D9%8A%D9%8A%D8%B1-%D9%85%D8%AC%D9%84%D8%AF-%D8%AA%D8%AE%D8%B2%D9%8A%D9%86-%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-mysql-%D8%A5%D9%84%D9%89-%D9%85%D9%83%D8%A7%D9%86%D9%8D-%D8%A2%D8%AE%D8%B1-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D8%A7%D9%84%D9%88%D8%B5%D9%84%D8%A7%D8%AA-%D8%A7%D9%84%D8%B1%D9%85%D8%B2%D9%8A%D8%A9-r307/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2017_03/main.png.925132f9c934693b4b383cf8c5fdfce4.png" /></p>

<p>
	 <span style='color: rgb(97, 101, 113); font-family: "Noto Kufi Arabic", "Open Sans", "Helvetica Neue", Helvetica, Tahoma, Arial, sans-serif; font-size: 18px;'>تمهيد</span>
</p>

<p>
	تتوسع قواعد البيانات بسرعة مع مرور الزمن، وتكاد في بعض الأحيان أن تملأ المساحة التخزينية المتاحة في نظام الملفات كلها. وقد تتعرض أيضًا إلى مشاكل في الإدخال والإخراج نتيجةً لمحاولة عدِّة خدمات الكتابة على (أو القراءة من) نفس القسم معًا.
</p>

<p style="text-align: center;">
	<img alt="main.png" class="ipsImage ipsImage_thumbnailed" data-fileid="22246" data-unique="af4w4r2wi" src="https://academy.hsoub.com/uploads/monthly_2017_03/main.png.5b0a036eb6e118a5d0f045e674f71d31.png"><br>
	هذا الدرس سيفيدك لو كنتَ تريد إضافة المزيد من المساحة التخزينية، أو استخدام خصائص جهاز التخزين لزيادة الأداء (ربما عبر استخدام RAID)، أو تتطلّع إلى استعمال ميزات أخرى للتخزين. سيعلِّمُك هذا الدرس طريقة تغيير مجلد تخزين بيانات MySQL.<br>
	التعليمات المذكورة هنا تناسب الخواديم التي تُشغِّل نسخةً وحيدةً من MySQL، أمّا لو كانت عندك أكثر من نسخة، فسيساعدك درس «<a href="https://www.digitalocean.com/community/tutorials/how-to-move-a-mysql-data-directory-to-a-new-location-on-ubuntu-16-04" rel="external nofollow">How To Move a MySQL Data Directory to a New Location on Ubuntu 16.04</a>» في ذلك، لأنَّه يحتوي معلومات عن كيفية تغيير مكان التخزين عبر تعديل الضبط.
</p>

<h3 id="المتطلبات-المسبقة">
	المتطلبات المسبقة
</h3>

<ul>
<li>
		خادوم أوبنتو 16.04 (أو 14.04) مضبوطٌ كما في درس «<a href="https://academy.hsoub.com/devops/servers/%D8%A7%D9%84%D8%A5%D8%B9%D8%AF%D8%A7%D8%AF-%D8%A7%D9%84%D8%A7%D8%A8%D8%AA%D8%AF%D8%A7%D8%A6%D9%8A-%D9%84%D8%AE%D8%A7%D8%AF%D9%88%D9%85-%D8%A3%D9%88%D8%A8%D9%86%D8%AA%D9%88-1404-r4/" rel="">الإعداد الابتدائي لخادوم أوبنتو 14.04</a>»، بما في ذلك إعداد حساب مستخدم عادي لكنه يملك امتيازات الجذر (root) عبر الأداة <code>sudo</code>.
	</li>
	<li>
		خادوم MySQL. لو لم يكن عندك خادوم MySQL مضبوطٌ مسبقًا، فسيساعدك الدرس «<a href="https://academy.hsoub.com/devops/servers/databases/%D8%AA%D8%AB%D8%A8%D9%8A%D8%AA-%D9%88%D8%A5%D8%B9%D8%AF%D8%A7%D8%AF-%D9%86%D8%B8%D8%A7%D9%85%D9%8A-%D8%A5%D8%AF%D8%A7%D8%B1%D8%A9-%D9%82%D9%88%D8%A7%D8%B9%D8%AF-%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-mysql-%D9%88postgresql-%D8%B9%D9%84%D9%89-%D8%A3%D9%88%D8%A8%D9%86%D8%AA%D9%88-r194/" rel="">تثبيت وإعداد نظامي إدارة قواعد البياناتMySQL وPostgreSQL على أوبنتو</a>».
	</li>
	<li>
		نسخة احتياطية من قواعد بياناتك. ما لم تكن تتعامل مع نسخةٍ حديثة التثبيت من MySQL، فاحرص على أخذ نسخة احتياطية من بياناتك. سيساعدك درس «<a href="https://academy.hsoub.com/devops/servers/databases/mysql/%D9%83%D9%8A%D9%81-%D8%AA%D9%82%D9%88%D9%85-%D8%A8%D8%A7%D9%84%D9%86%D8%B3%D8%AE-%D8%A7%D9%84%D8%A7%D8%AD%D8%AA%D9%8A%D8%A7%D8%B7%D9%8A-%D9%84%D9%82%D9%88%D8%A7%D8%B9%D8%AF-%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-mysql-%D8%B9%D9%84%D9%89-ubuntu-r110/" rel="">كيف تقوم بالنسخ الاحتياطي لقواعد بيانات MySQL على Ubuntu</a>» على فعل ذلك.
	</li>
</ul>
<p>
	سننقل البيانات من جهاز تخزينٍ موصولٍ (mounted) في نقطة الوصل <code>‎/mnt/volume-nyc1-01</code>..
</p>

<p>
	سيعلّمك هذا الدرس طريقة نقل مجلد تخزين بيانات MySQL إلى مكانٍ جديد بغض النظر عن وسيط التخزين الذي تستخدمه (قرص صلب، أو مصفوفة RAID، أو تخزين شبكي).
</p>

<h3 id="الخطوة-الأولى-نقل-مجلد-بيانات-mysql">
	الخطوة الأولى: نقل مجلد بيانات MySQL
</h3>

<p>
	لكي نضمن سلامة البيانات، علينا أولًا إيقاف خادوم MySQL:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_6413_9">
<code class="hljs bash"><span class="hljs-built_in">sudo</span> systemctl stop mysql</code></pre>

<p>
	الأمر <code>systemctl</code> لا يُظهِر نتيجة تنفيذ أوامر إدارة الخدمات، لذا إذا أردتَ التحقق أنَّ الخادوم قد أُغلِق بنجاح، فنفِّذ الأمر الآتي:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_6413_9">
<code class="hljs bash"><span class="hljs-built_in">sudo</span> systemctl status mysql</code></pre>

<p>
	انظر إلى آخر سطر من ناتج الأمر السابق الذي يجب أن يخبرك أنَّ الخادوم قد توقف عن العمل:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_6413_9">
<code class="hljs css">. . .
<span class="hljs-tag">Jul</span> 18 11<span class="hljs-pseudo">:24</span><span class="hljs-pseudo">:20</span> <span class="hljs-tag">ubuntu-512mb-nyc1-01</span> <span class="hljs-tag">systemd</span><span class="hljs-attr_selector">[1]</span>: <span class="hljs-tag">Stopped</span> <span class="hljs-tag">MySQL</span> <span class="hljs-tag">Community</span> <span class="hljs-tag">Server</span>.</code></pre>

<p>
	نستطيع الآن –بعد إغلاق الخادوم– نقل مجلد قواعد البيانات إلى مكانٍ آخر:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_6413_9">
<code class="hljs lasso">sudo mv /<span class="hljs-built_in">var</span>/lib/mysql /mnt/volume<span class="hljs-attribute">-nyc1</span><span class="hljs-subst">-</span><span class="hljs-number">01</span>/mysql</code></pre>

<p>
	ثم سنُنشِئ وصلةً رمزيةً (symbolic link):
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_6413_9">
<code class="hljs lasso"><span class="pln">sudo ln </span><span class="hljs-attribute"><span class="pun">-</span><span class="pln">s</span></span><span class="pln"> </span><span class="pun">/</span><span class="pln">mnt</span><span class="pun">/</span><span class="pln">volume</span><span class="hljs-attribute"><span class="pun">-</span><span class="pln">nyc1</span></span><span class="hljs-subst"><span class="pun">-</span></span><span class="hljs-number"><span class="lit">01</span></span><span class="pun">/</span><span class="pln">mysql </span><span class="pun">/</span><span class="hljs-built_in"><span class="kwd">var</span></span><span class="pun">/</span><span class="pln">lib</span><span class="pun">/</span><span class="pln">mysql</span></code></pre>

<p>
	يبدو أنَّنا نستطيع تشغيل خادوم MySQL بعد إنشاء الوصلة الرمزية، لكن هنالك أمرٌ إضافيٌ يجب ضبطه.
</p>

<h3 id="الخطوة-الثانية-ضبط-قواعد-الوصول-في-apparmor">
	الخطوة الثانية: ضبط قواعد الوصول في AppArmor
</h3>

<p>
	بعد أن نقلتَ مجلد MySQL إلى مكانٍ آخر في نظام الملفات، فعليك أن تُعدِّل في ضبط AppArmor، وذلك بتعديل ملف <code>alias</code> التابع لبرمجية AppArmor:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_6413_9">
<code class="hljs bash"><span class="hljs-built_in">sudo</span> nano /etc/apparmor.d/tunables/alias</code></pre>

<p>
	أضف الآن التعليمة الآتية في نهاية الملف:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_6413_9">
<code class="hljs coffeescript">. . .
alias <span class="hljs-regexp">/var/lib/mysql/</span><span class="hljs-function"> -&gt;</span> <span class="hljs-regexp">/mnt/volume-nyc1-01/mysql/</span>,</code></pre>

<p>
	لكي تأخذ التعديلات مفعولها، فيجب إعادة تشغيل AppArmor:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_6413_9">
<code class="hljs bash"><span class="hljs-built_in">sudo</span> systemctl restart apparmor</code></pre>

<p>
	ملاحظة: إذا تخطيت خطوة ضبط AppArmor وحاولت تشغيل <code>mysql</code> مباشرةً، فستظهر لك رسالة الخطأ الآتية:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_6413_9">
<span class="typ">Job</span><span class="pln"> </span><span class="kwd">for</span><span class="pln"> mysql</span><span class="pun">.</span><span class="pln">service failed because the control process 
exited </span><span class="kwd">with</span><span class="pln"> error code</span><span class="pun">.</span><span class="pln"> </span><span class="typ">See</span><span class="pln"> </span><span class="str">"systemctl status mysql.service"</span><span class="pln"> 
</span><span class="kwd">and</span><span class="pln"> </span><span class="str">"journalctl -xe"</span><span class="pln"> </span><span class="kwd">for</span><span class="pln"> details</span><span class="pun">.</span></pre>

<p>
	يمكن تلخيص الناتج الظاهر من الأمرَين <code>systemctl</code> و <code>journalctl</code> بما يلي:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_6413_9">
<code class="hljs fix"><span class="hljs-attribute">Jul 18 11:03:24 ubuntu-512mb-nyc1-01 systemd[1]: 
mysql.service: Main process exited, code</span>=<span class="hljs-string">exited, status=1/FAILURE</span></code></pre>

<p>
	ولمّا كانت رسائل الخطأ لا تُظهِر ربطًا مباشرًا بين AppArmor ومجلد التخزين، فقد يصعب عليك أن تعرف لماذا يحدث هذا الخطأ. لكن إن نظرنا إلى ملف <code>syslog</code> فسنرى ما هي المشكلة:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_6413_9">
<code class="hljs lasso">sudo tail /<span class="hljs-built_in">var</span>/<span class="hljs-keyword">log</span>/syslog</code></pre>

<p>
	الناتج:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_6413_9">
<code class="hljs rust"><span class="typ">Nov</span><span class="pln"> </span><span class="hljs-number"><span class="lit">24</span></span><span class="pln"> </span><span class="hljs-number"><span class="lit">00</span></span><span class="pun">:</span><span class="hljs-number"><span class="lit">03</span></span><span class="pun">:</span><span class="hljs-number"><span class="lit">40</span></span><span class="pln"> digitalocean kernel</span><span class="pun">:</span><span class="pln"> 
</span><span class="pun">[</span><span class="pln">  </span><span class="hljs-number"><span class="lit">437.735748</span></span><span class="pun">]</span><span class="pln"> audit</span><span class="pun">:</span><span class="pln"> </span><span class="hljs-keyword"><span class="pln">type</span></span><span class="pun">=</span><span class="hljs-number"><span class="lit">1400</span></span><span class="pln"> audit</span><span class="pun">(</span><span class="hljs-number"><span class="lit">1479945820.037</span></span><span class="pun">:</span><span class="hljs-number"><span class="lit">20</span></span><span class="pun">):</span><span class="pln"> 
apparmor</span><span class="pun">=</span><span class="hljs-string"><span class="str">"DENIED"</span></span><span class="pln"> operation</span><span class="pun">=</span><span class="hljs-string"><span class="str">"mknod"</span></span><span class="pln"> profile</span><span class="pun">=</span><span class="hljs-string"><span class="str">"/usr/sbin/mysqld"</span></span><span class="pln"> 
name</span><span class="pun">=</span><span class="hljs-string"><span class="str">"/mnt/volume-nyc1-01/mysql/mysql.lower-test"</span></span><span class="pln"> <abbr title="Process IDentifier | معرّف العملية أو البرنامج">pid</abbr></span><span class="pun">=</span><span class="hljs-number"><span class="lit">4228</span></span><span class="pln"> 
</span><span class="hljs-keyword"><span class="pln">comm</span></span><span class="pun">=</span><span class="hljs-string"><span class="str">"mysqld"</span></span><span class="pln"> requested_mask</span><span class="pun">=</span><span class="hljs-string"><span class="str">"c"</span></span><span class="pln"> denied_mask</span><span class="pun">=</span><span class="hljs-string"><span class="str">"c"</span></span><span class="pln"> fsuid</span><span class="pun">=</span><span class="hljs-number"><span class="lit">112</span></span><span class="pln"> ouid</span><span class="pun">=</span><span class="hljs-number"><span class="lit">112</span></span></code></pre>

<p>
	يمكننا الآن أن نُشغِّل خدمة MySQL:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_6413_9">
<code class="hljs bash"><span class="hljs-built_in">sudo</span> systemctl start mysql
<span class="hljs-built_in">sudo</span> systemctl status mysql</code></pre>

<p>
	بعد أن تُعيد تشغيل MySQL، فتحقق أنَّ بياناتك سليمة وأنَّ خادوم MySQL يعمل عملًا سليمًا دون مشاكل.
</p>

<h3 id="الخلاصة">
	الخلاصة
</h3>

<p>
	نقلنا في هذا الدرس مجلد تخزين بيانات MySQL واستعملها وصلةً رمزيةً لكي نخبر MySQL ما هو مكان التخزين الجديد؛ ثم حدّثنا ضبط برمجية AppArmor (الموجودة في توزيعة أوبنتو وغيرها) لكي يتوافق مع ما عدّلناه. وصحيحٌ أننا استعملنا جهاز تخزين مستقل، إلا أنَّك تستطيع اتباع تعليمات هذا الدرس لإعادة تعريف مكان تخزين البيانات بغض النظر عن تقنية التخزين المستعملة.
</p>

<p>
	ترجمة -وبتصرّف- للمقال <a href="https://www.digitalocean.com/community/tutorials/how-to-change-a-mysql-data-directory-to-a-new-location-using-a-symlink" rel="external nofollow">How to Change a MySQL Data Directory to a New Location Using a Symlink</a> لصاحبته Melissa Anderson
</p>
]]></description><guid isPermaLink="false">307</guid><pubDate>Thu, 16 Mar 2017 16:36:05 +0000</pubDate></item><item><title>&#x627;&#x633;&#x62A;&#x62E;&#x62F;&#x627;&#x645; &#x627;&#x644;&#x62F;&#x648;&#x627;&#x644; &#x641;&#x64A; &#x642;&#x648;&#x627;&#x639;&#x62F; &#x628;&#x64A;&#x627;&#x646;&#x627;&#x62A; MySQL</title><link>https://academy.hsoub.com/devops/servers/databases/mysql/%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D8%A7%D9%84%D8%AF%D9%88%D8%A7%D9%84-%D9%81%D9%8A-%D9%82%D9%88%D8%A7%D8%B9%D8%AF-%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-mysql-r299/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2017_02/mysql-004.png.7d574d401077fff5f7edede1c5270156.png" /></p>

<p id="استخدام-الدوال-في-قواعد-بيانات-mysql">
	سنشرح في هذه الدرس كيفية تقليل عدد السجلات المُعادة من طلبية SELECT، وطريقة ترتيب الناتج بناءً على شرطٍ معيّن.<br>
	إضافةً إلى ما سبق، سنتعلم كيفية تجميع السجلات وإجراء عمليات حسابية أساسية على الحقول الرقمية، وكل ما سبق سيساعدنا على إنشاء سكربت SQL الذي سنستخدمه لإنشاء تقارير مفيدة.<br>
	إذا لم تكن لديك خلفية جيّدة حول قواعد بيانات MySQL <a href="https://academy.hsoub.com/devops/servers/databases/mysql/%D8%AA%D8%B9%D9%84%D9%85-%D8%A3%D8%B3%D8%A7%D8%B3%D9%8A%D8%A7%D8%AA-mysql-r297/" rel="">فأنصحك بقراءة هذا الدّرس أوّلا</a>
</p>

<p style="text-align: center;">
	<img class="ipsImage ipsImage_thumbnailed" data-fileid="21677" data-unique="beqvu7ik9" src="https://academy.hsoub.com/uploads/monthly_2017_02/mysql-004.png.985ffbb8657038413c480f41513eead8.png" alt="mysql-004.png"></p>

<h2 id="المتطلبات-المسبقة">
	المتطلبات المسبقة
</h2>

<p>
	عليك اتباع الخطوات الآتية قبل المتابعة:
</p>

<ul>
<li>
		 نزِّل قاعدة بيانات <code>employees</code>، التي تحتوي على ستة جداول تتضمن حوالي 4 ملايين سجل إجماليًا:
	</li>
</ul>
<pre class="ipsCode" id="ips_uid_9749_7">
# wget https://launchpad.net/test-db/employees-db-1/1.0.6/+download/employees_db-full-1.0.6.tar.bz2
# tar xjf employees_db-full-1.0.6.tar.bz2
# cd employees_db</pre>

<ul>
<li>
		ادخل إلى مِحَث MariaDB وأنشِئ قاعدة بيانات باسم <code>employees</code>:
	</li>
</ul>
<ol>
<li>
		<pre class="ipsCode" id="ips_uid_9749_9">
# mysql -u root -p
Enter password: 
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 2
Server version: 10.1.14-MariaDB MariaDB Server
Copyright (c) 2000, 2016, Oracle, MariaDB Corporation Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MariaDB [(none)]&gt; CREATE DATABASE employees;
Query OK, 1 row affected (0.00 sec)</pre>

		<p>
			 
		</p>
	</li>
</ol>
<ul>
<li>
		استورد قاعدة البيانات إلى خادوم MairaDB كالآتي:
	</li>
</ul>
<pre class="ipsCode" id="ips_uid_9749_11">
MariaDB [(none)]&gt; source employees.sql</pre>

<p>
	 
</p>

<p>
	انتظر دقيقةً أو دقيقتين إلى أن ينتهي استيراد قاعدة البيانات (أبقِ في بالك أننا نتحدث هنا عن أربعة ملايين سجل!).
</p>

<ul>
<li>
		 تأكد من أنَّ استيراد قاعدة البيانات قد تمَّ بشكلٍ صحيح بعرض جداولها:
	</li>
</ul>
<pre class="ipsCode" id="ips_uid_9749_13">
MariaDB [employees]&gt; USE employees;
Database changed
MariaDB [employees]&gt; SHOW TABLES;
+---------------------+
| Tables_in_employees |
+---------------------+
| departments         |
| dept_emp            |
| dept_manager        |
| employees           |
| salaries            |
| titles              |
+---------------------+
6 rows in set (0.02 sec)</pre>

<ul>
<li>
		أنشِئ حسابًا مخصصًا لاستخدام قاعدة بيانات <code>employees</code> (اختر اسمًا وكلمة مرور):
	</li>
</ul>
<pre class="ipsCode" id="ips_uid_9749_15">
MariaDB [employees]&gt; CREATE USER empadmin@localhost IDENTIFIED BY 'empadminpass';
Query OK, 0 rows affected (0.03 sec)
MariaDB [employees]&gt; GRANT ALL PRIVILEGES ON  employees.* to empadmin@localhost;
Query OK, 0 rows affected (0.02 sec)
MariaDB [employees]&gt; FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.00 sec)
MariaDB [employees]&gt; exit
Bye</pre>

<p>
	 
</p>

<ul>
<li>
		سجِّل دخولك الآن إلى مِحَث MariaDB بالمستخدم <code>empadmin</code>:
	</li>
</ul>
<pre class="ipsCode" id="ips_uid_9749_18">
# mysql -u empadmin -p
Enter password: 
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 4
Server version: 10.1.14-MariaDB MariaDB Server
Copyright (c) 2000, 2016, Oracle, MariaDB Corporation Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MariaDB [(none)]&gt; USE employees;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed</pre>

<p>
	احرص على تنفيذ جميع الخطوات الست السابقة قبل إكمالك لقراءة هذا الدرس.
</p>

<h2 id="ترتيب-وتقليل-عدد-السجلات-المعروضة">
	ترتيب وتقليل عدد السجلات المعروضة
</h2>

<p>
	جدول الرواتب <code>salaries</code> يحتوي على جميع واردات كل موظف مع تاريخ البداية والنهاية. ربما تود أن تعرض رواتب الموظف <code>emp_no=10001</code> خلال فترةٍ من الزمن. وهذا سيساعدك على الإجابة عن التساؤلات الآتية:
</p>

<ul>
<li>
		هل حصل على زيادة في راتبه؟
	</li>
	<li>
		إذا حدث ذلك، فمتى؟
	</li>
</ul>
<p>
	نفِّذ الأمر الآتي لمعرفة ذلك:
</p>

<pre class="ipsCode" id="ips_uid_9749_20">
MariaDB [employees]&gt; SELECT * FROM salaries WHERE emp_no=10001 ORDER BY from_date;
+--------+--------+------------+------------+
| emp_no | salary | from_date  | to_date    |
+--------+--------+------------+------------+
|  10001 |  60117 | 1986-06-26 | 1987-06-26 |
|  10001 |  62102 | 1987-06-26 | 1988-06-25 |
|  10001 |  66074 | 1988-06-25 | 1989-06-25 |
|  10001 |  66596 | 1989-06-25 | 1990-06-25 |
|  10001 |  66961 | 1990-06-25 | 1991-06-25 |
|  10001 |  71046 | 1991-06-25 | 1992-06-24 |
|  10001 |  74333 | 1992-06-24 | 1993-06-24 |
|  10001 |  75286 | 1993-06-24 | 1994-06-24 |
|  10001 |  75994 | 1994-06-24 | 1995-06-24 |
|  10001 |  76884 | 1995-06-24 | 1996-06-23 |
|  10001 |  80013 | 1996-06-23 | 1997-06-23 |
|  10001 |  81025 | 1997-06-23 | 1998-06-23 |
|  10001 |  81097 | 1998-06-23 | 1999-06-23 |
|  10001 |  84917 | 1999-06-23 | 2000-06-22 |
|  10001 |  85112 | 2000-06-22 | 2001-06-22 |
|  10001 |  85097 | 2001-06-22 | 2002-06-22 |
|  10001 |  88958 | 2002-06-22 | 9999-01-01 |
+--------+--------+------------+------------+
17 rows in set (0.03 sec)</pre>

<p>
	لكن ماذا لو أردنا معرفة آخر خمس زيادات؟ يمكننا أن نستخدم <code>ORDER BY form_date DESC</code>. تُشير الكلمة المحجوزة <code>DESC</code> إلى أنَّ الترتيب الذي نريد اتباعه هو الترتيب التنازلي.<br>
	إضافةً إلى ما سبق، يسمح لنا التعبير <code>LIMIT 5</code> بإعادة أوّل خمسة سجلات:
</p>

<pre class="ipsCode" id="ips_uid_9749_22">
MariaDB [employees]&gt; SELECT * FROM salaries WHERE emp_no=10001 ORDER BY from_date DESC LIMIT 5;
+--------+--------+------------+------------+
| emp_no | salary | from_date  | to_date    |
+--------+--------+------------+------------+
|  10001 |  88958 | 2002-06-22 | 9999-01-01 |
|  10001 |  85097 | 2001-06-22 | 2002-06-22 |
|  10001 |  85112 | 2000-06-22 | 2001-06-22 |
|  10001 |  84917 | 1999-06-23 | 2000-06-22 |
|  10001 |  81097 | 1998-06-23 | 1999-06-23 |
+--------+--------+------------+------------+
5 rows in set (0.00 sec)</pre>

<p>
	يمكنك أيضًا استخدام <code>ORDER BY</code> على عدِّة حقول، فمثلًا ستُرتِّب الطلبية الآتية النتائج اعتمادًا على تاريخ ولادة الموظف تصاعديًا (وهو الترتيب الافتراضي) ثم عبر اسم الموظف الأخير بترتيبٍ هجائيٍ تنازلي:
</p>

<pre class="ipsCode" id="ips_uid_9749_24">
MariaDB [employees]&gt; SELECT CONCAT(last_name, ', ', first_name) AS Name, gender AS Gender,  hire_date AS "Hire date" FROM employees ORDER BY birth_date, last_name DESC LIMIT 10;
+--------------------+--------+------------+
| Name               | Gender | Hire date  |
+--------------------+--------+------------+
| Whitcomb, Kiyokazu | M      | 1988-07-26 |
| Schaad, Ronghao    | M      | 1988-07-10 |
| Remmele, Supot     | M      | 1989-01-27 |
| Pocchiola, Jouni   | M      | 1985-03-10 |
| Kuzuoka, Eishiro   | M      | 1992-02-12 |
| Decaestecker, Moni | M      | 1986-10-06 |
| Wiegley, Mircea    | M      | 1985-07-18 |
| Vendrig, Sachar    | M      | 1985-11-04 |
| Tsukuda, Cedric    | F      | 1993-12-12 |
| Tischendorf, Percy | M      | 1986-11-10 |
+--------------------+--------+------------+
10 rows in set (0.31 sec)</pre>

<p>
	يمكنك معرفة المزيد من المعلومات عن <code>LIMIT</code> في <a href="https://mariadb.com/kb/en/mariadb/select/#limit" rel="external nofollow">الدليل الرسمي</a>.
</p>

<h2 id="تجميع-السجلات-واستخدام-max-و-min-و-avg-و-round">
	تجميع السجلات، واستخدام MAX و MIN و AVG و ROUND
</h2>

<p>
	كما ذكرنا سابقًا، الجدول <code>salaries</code> يحتوي على رواتب الموظفين خلال فترات زمنية، وبجانب استخدام <code>LIMIT</code>، يمكننا استخدام الكلمتين المحجوزتين <code>MAX</code> و <code>MIN</code> لتحديد متى كان أعلى راتب وأدنى راتب لموظفين معينين:
</p>

<pre class="ipsCode" id="ips_uid_9749_26">
MariaDB [employees]&gt; SELECT CONCAT(last_name, ', ', first_name) AS Name, MAX(B.salary) AS "Max. salary" FROM employees A JOIN salaries B ON A.emp_no = B.emp_no WHERE A.emp_no IN (10001, 10002, 10003) GROUP BY A.emp_no;
+-----------------+-------------+
| Name            | Max. salary |
+-----------------+-------------+
| Facello, Georgi |       88958 |
| Simmel, Bezalel |       72527 |
| Bamford, Parto  |       43699 |
+-----------------+-------------+
3 rows in set (0.02 sec)
MariaDB [employees]&gt; SELECT CONCAT(last_name, ', ', first_name) AS Name, MIN(B.salary) AS "Min. salary" FROM employees A JOIN salaries B ON A.emp_no = B.emp_no WHERE A.emp_no IN (10001, 10002, 10003) GROUP BY A.emp_no;
+-----------------+-------------+
| Name            | Min. salary |
+-----------------+-------------+
| Facello, Georgi |       60117 |
| Simmel, Bezalel |       65828 |
| Bamford, Parto  |       40006 |
+-----------------+-------------+
3 rows in set (0.00 sec)</pre>

<p>
	وبناءً على النتائج السابقة، هل تستطيع أن تعرف ماهو ناتج الطلبية الآتية:
</p>

<pre class="ipsCode" id="ips_uid_9749_28">
MariaDB [employees]&gt; SELECT CONCAT(last_name, ', ', first_name) AS Name, ROUND(AVG(B.salary), 2) AS "Avg. salary" FROM employees A JOIN salaries B ON A.emp_no = B.emp_no WHERE A.emp_no IN (10001, 10002, 10003) GROUP BY A.emp_no;
+-----------------+-------------+
| Name            | Avg. salary |
+-----------------+-------------+
| Facello, Georgi |    75388.94 |
| Simmel, Bezalel |    68854.50 |
| Bamford, Parto  |    43030.29 |
+-----------------+-------------+
3 rows in set (0.01 sec)</pre>

<p>
	إذا توقعتَ أنَّ الناتج هو المتوسط الحسابي (عبر <code>AVG</code>) للراتب مقرّبًا إلى منزلتين عشريتين (عبر <code>ROUND</code>)، فأنت مصيب.<br>
	إذا أردنا أن نعرف مجموع رواتب الموظفين وإعادة أوّل خمسة، فيمكننا حينها استعمال الطلبية الآتية:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9749_30">
<span class="typ">MariaDB</span><span class="pln"> </span><span class="pun">[</span><span class="pln">employees</span><span class="pun">]&gt;</span><span class="pln"> SELECT emp_no</span><span class="pun">,</span><span class="pln"> SUM</span><span class="pun">(</span><span class="pln">salary</span><span class="pun">)</span><span class="pln"> AS </span><span class="typ">Salary</span><span class="pln"> FROM salaries GROUP BY emp_no ORDER BY </span><span class="typ">Salary</span><span class="pln"> DESC LIMIT </span><span class="lit">5</span><span class="pun">;</span><span class="pln">
</span><span class="pun">+--------+---------+</span><span class="pln">
</span><span class="pun">|</span><span class="pln"> emp_no </span><span class="pun">|</span><span class="pln"> </span><span class="typ">Salary</span><span class="pln">  </span><span class="pun">|</span><span class="pln">
</span><span class="pun">+--------+---------+</span><span class="pln">
</span><span class="pun">|</span><span class="pln"> </span><span class="lit">109334</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="lit">2553036</span><span class="pln"> </span><span class="pun">|</span><span class="pln">
</span><span class="pun">|</span><span class="pln">  </span><span class="lit">43624</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="lit">2492873</span><span class="pln"> </span><span class="pun">|</span><span class="pln">
</span><span class="pun">|</span><span class="pln">  </span><span class="lit">66793</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="lit">2383923</span><span class="pln"> </span><span class="pun">|</span><span class="pln">
</span><span class="pun">|</span><span class="pln"> </span><span class="lit">237542</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="lit">2381119</span><span class="pln"> </span><span class="pun">|</span><span class="pln">
</span><span class="pun">|</span><span class="pln">  </span><span class="lit">47978</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="lit">2374024</span><span class="pln"> </span><span class="pun">|</span><span class="pln">
</span><span class="pun">+--------+---------+</span><span class="pln">
</span><span class="lit">5</span><span class="pln"> rows in </span><span class="typ">set</span><span class="pln"> </span><span class="pun">(</span><span class="lit">2.22</span><span class="pln"> sec</span><span class="pun">)</span></pre>

<p>
	جمّعنا الرواتب في الطلبية السابقة عبر الموظف، ثم أجرينا عليها عملية <code>SUM</code>.
</p>

<h2 id="تجميع-المعلومات-السابقة-في-سكربت">
	تجميع المعلومات السابقة في سكربت
</h2>

<p>
	لحسن الحظ، لا نحتاج إلى تشغيل طلبية تلو أخرى لإنشاء تقرير، وإنما نستطيع إنشاء سكربت فيه سلسلة من تعليمات SQL التي تُعيد جميع النتائج المطلوبة.<br>
	بعد تنفيذ السكربت، فستظهر جميع النتائج دون تدخل منا، ولنسمِّ الملف باسم <code>maxminavg.sql</code> في مجلد العمل الحالي وفيه المحتويات الآتية:
</p>

<pre class="ipsCode" id="ips_uid_9749_32">
--Select database
USE employees;
--Calculate maximum salaries
SELECT CONCAT(last_name, ', ', first_name) AS Name, MAX(B.salary) AS "Max. salary" FROM employees A JOIN salaries B ON A.emp_no = B.emp_no WHERE A.emp_no IN (10001, 10002, 10003) GROUP BY A.emp_no;
--Calculate minimum salaries
SELECT CONCAT(last_name, ', ', first_name) AS Name, MIN(B.salary) AS "Min. salary" FROM employees A JOIN salaries B ON A.emp_no = B.emp_no WHERE A.emp_no IN (10001, 10002, 10003) GROUP BY A.emp_no;
--Calculate averages, round to 2 decimal places
SELECT CONCAT(last_name, ', ', first_name) AS Name, ROUND(AVG(B.salary), 2) AS "Avg. salary" FROM employees A JOIN salaries B ON A.emp_no = B.emp_no WHERE A.emp_no IN (10001, 10002, 10003) GROUP BY A.emp_no;</pre>

<p>
	الأسطر التي تبدأ بشرطتين <code>--</code> هي تعليقات وسيتم تجاهلها. وستُنفَّذ الطلبيات تلو بعضها. ويمكننا تنفيذ هذا السكربت إما من سطر أوامر لينكس:
</p>

<pre class="ipsCode" id="ips_uid_9749_34">
# mysql -u empadmin -p &lt; maxminavg.sql
Enter password: 
Name    Max. salary
Facello, Georgi 88958
Simmel, Bezalel 72527
Bamford, Parto  43699
Name    Min. salary
Facello, Georgi 60117
Simmel, Bezalel 65828
Bamford, Parto  40006
Name    Avg. salary
Facello, Georgi 75388.94
Simmel, Bezalel 68854.50
Bamford, Parto  43030.29</pre>

<p>
	أو من مِحث MariaDB:
</p>

<pre class="ipsCode" id="ips_uid_9749_36">
# mysql -u empadmin -p
Enter password: 
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 4
Server version: 10.1.14-MariaDB MariaDB Server
Copyright (c) 2000, 2016, Oracle, MariaDB Corporation Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MariaDB [(none)]&gt; source maxminavg.sql
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed</pre>

<h2 id="الخلاصة">
	الخلاصة
</h2>

<p>
	شرحنا في هذه المقالة كيفية استخدام عدِّة دوال في MariaDB لتحسين النتائج التي يُخرجها الاستعلام <code>SELECT</code>. وبعد أن تكتب الاستعلامات لأول مرة، فيمكنك بكل بساطة وضعها داخل سكربت وتنفيذها بسهولة مما سيُقلِّل من الخطأ البشري عند كتابتها.<br>
	ترجمة -وبتصرّف- للمقال <a href="http://www.tecmint.com/learn-mysql-mariadb-advance-functions-sql-queries/" rel="external nofollow">Learn How to Use Several Functions of MySQL and MariaDB – Part 2</a> لصاحبه Gabriel Cánepa.
</p>
]]></description><guid isPermaLink="false">299</guid><pubDate>Thu, 16 Feb 2017 07:14:00 +0000</pubDate></item><item><title>&#x62A;&#x639;&#x644;&#x645; &#x623;&#x633;&#x627;&#x633;&#x64A;&#x627;&#x62A; MySQL</title><link>https://academy.hsoub.com/devops/servers/databases/mysql/%D8%AA%D8%B9%D9%84%D9%85-%D8%A3%D8%B3%D8%A7%D8%B3%D9%8A%D8%A7%D8%AA-mysql-r297/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2017_01/mysql-003.png.c583d34a8d6531fea8ae7887d5bba990.png" /></p>

<p id="تعلم-أساسيات-mysql">
	سنشرح في هذا الدرس كيفية إنشاء قاعدة بيانات، وجداول (مع تبيان أنواع بيانات حقولها)، وسنفصّل طريقة إجراء عمليات على البيانات على خادوم MySQL أو MariaDB.<br>
	سنفترض أنَّك قد ثبّتَ الحزم اللازمة على نظامك، ونفّذتَ الأمر <code>mysql_secure_installation</code> لتحسين حماية خادوم قواعد البيانات. وإلا فانظر إلى درسنا عن كيفية <a href="https://academy.hsoub.com/devops/servers/databases/%D8%AA%D8%AB%D8%A8%D9%8A%D8%AA-%D9%88%D8%A5%D8%B9%D8%AF%D8%A7%D8%AF-%D9%86%D8%B8%D8%A7%D9%85%D9%8A-%D8%A5%D8%AF%D8%A7%D8%B1%D8%A9-%D9%82%D9%88%D8%A7%D8%B9%D8%AF-%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-mysql-%D9%88postgresql-%D8%B9%D9%84%D9%89-%D8%A3%D9%88%D8%A8%D9%86%D8%AA%D9%88-r194/" rel="">تثبيت خادوم MySQL/MariaDB</a> .<br>
	للاختصار، سنشير إلى قواعد البيانات باسم «MariaDB» في هذا الدرس، لكن نفس الاصطلاحات والتعليمات المشروحة هنا ستنطبق تمامًا على MySQL.
</p>

<h2 id="إنشاء-قواعد-البيانات-والجداول-والمستخدمين">
	إنشاء قواعد البيانات والجداول والمستخدمين
</h2>

<p>
	كما تعلم، يمكن تعريف قواعد البيانات بأبسط الكلمات على أنها مجموعة منظمة من المعلومات؛ وندعو قواعد MariaDB تحديدًا أنَّها نظام إدارة قواعد بيانات علائقية (relational database management system اختصارًا RDBMS) التي تستخدم لغة الاستعلام البنيوية (Structure Query Language أي SQL) لإجراء العمليات على قواعد البيانات. أبقِ في بالك أنَّ MariaDB تستعمل الاصطلاحين «database» (قاعدة بيانات) و «schema» (مخطط) لنفس المعنى تمامًا.<br>
	نستعمل الجداول (tables) لتخزين المعلومات الدائمة في قواعد البيانات التي تُخزَّن فيها «سجلاتٌ» (rows) من البيانات. وعادةً يرتبط جدولان أو أكثر مع بعضها بطريقةٍ ما. وهذا هو جزءٌ مهمٌ من عملية التنظيم التي تُميّز قواعد البيانات العلائقية.
</p>

<p style="text-align: center;">
	<img alt="mysql-003.png" class="ipsImage ipsImage_thumbnailed" data-fileid="20836" data-unique="u8k8yfiug" src="https://academy.hsoub.com/uploads/monthly_2017_01/mysql-003.png.6154746aab65d0a0ddb2a81af97fc4d5.png"></p>

<h2 id="إنشاء-قاعدة-بيانات-جديدة">
	إنشاء قاعدة بيانات جديدة
</h2>

<p>
	علينا أن ندخل أولًا إلى مِحَث (prompt) قواعد بيانات MariaDB بإدخال الأمر الآتي، وذلك لإنشاء قاعدة بيانات جديدة (سيُطلَب منك إدخال كلمة مرور المستخدم root لقواعد البيانات):
</p>

<pre class="ipsCode" id="ips_uid_706_8">
[root@TecMint ~]# mysql -u root -p
Enter password: 
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 2
Server version: 10.1.14-MariaDB MariaDB Server
Copyright (c) 2000, 2016, Oracle, MariaDB Corporation Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MariaDB [(none)]&gt; CREATE DATABASE BookstoreDB;
Query OK, 1 row affected (0.00 sec)
MariaDB [(none)]&gt; </pre>

<p>
	بعد إنشاء قاعدة البيانات، فسنحتاج إلى إنشاء جدولين على الأقل فيها، لكن دعنا أولًا نلقي نظرةً على مفهوم أنواع البيانات في الجداول.
</p>

<h2 id="لمحة-عن-أنواع-البيانات-في-قواعد-mariadb">
	لمحة عن أنواع البيانات في قواعد MariaDB
</h2>

<p>
	كما ذكرنا سابقًا، الجداول هي الكائن الرئيسية في قواعد البيانات والتي ستُخزَّن فيها المعلومات الدائمة. يتألف كل جدول من حقلين أو أكثر (تُعرَف أيضًا بالأعمدة [columns]) لها نوع بيانات معيّن (أي نوع المعلومات التي ستُخزَّن فيها) التي يستطيع كل حقلٍ (أو عمودٍ) تخزينها.<br>
	سأستعرض أشهر أنواع البيانات في MariaDB (يمكنك الرجوع إلى <a href="https://mariadb.com/kb/en/mariadb/data-types/" rel="external nofollow">الدليل الرسمي</a> لتحصل على قائمةٍ كاملةٍ):
</p>

<h3 id="أنواع-البيانات-الرقمية">
	أنواع البيانات الرقمية
</h3>

<ul>
<li>
		<code>BOOLEAN</code>: قيمٌ منطقيةٌ، وتعتبَر فيها القيم المساوية للصفر (0) على أنَّها false، وبقية القيم true.
	</li>
	<li>
		<code>TINYINT</code>: إذا استخدمَت مع الكلمة المحجوزة <code>SIGNED</code> فستُمثِّل المجال من ‎-128 إلى 127، بينما مجالها إن كانت <code>UNSIGNED</code> فهو من 0 إلى 255.
	</li>
	<li>
		<code>SMALLINT</code>: إذا استخدمت مع <code>SIGNED</code> فهي تمثِّل المجال من ‎-32768 إلى 32767. بينما مجال <code>UNSIGNED</code> فهو من 0 إلى 65535.
	</li>
	<li>
		<code>INT</code>: إذا استخدمت مع <code>SIGNED</code> فهي تغطي المجال من 0 إلى 4294967295، ومن ‎‎-2147483648 إلى 2147483647 فيما عدا ذلك.<br>
		ملاحظة: في أنواع البيانات <code>TINYINT</code> و <code>SMAILLINT</code> و <code>INT</code>، القيمة الافتراضية المرتبطة معها هي <code>SIGNED</code>.
	</li>
	<li>
		<code>DOUBLE(M, D)</code>: يُمثِّل هذا النوع الأعداد العشرية ذات الفاصلة، حيث <code>M</code> هو العدد الكلي للأرقام و <code>D</code> هو عدد الأرقام بعد الفاصلة العشرية. إذا اُستعمِلَت الكلمة <code>UNSIGND</code> فلن يُسمَح بإدراج قيم سالبة في هذا الحقل.
	</li>
</ul>
<h3 id="أنواع-البيانات-النصية">
	أنواع البيانات النصية
</h3>

<ul>
<li>
		<code>VARCHAR(M)</code>: يُمثِّل هذا النوع السلاسل النصية ذات الطول المتغير حيث <code>M</code> هو عدد الأحرف المسموح الأقصى للسلسلة النصية مقدرًا بالبايت (يمكن أن يبلغ نظريًا 65535 بايت). في حال كانت السلاسل النصية المُدخَلة بالإنكليزية، فسيأخذ كل محرف بايتًا واحدًا، لكن هنالك استثناءٌ لبعض المحارف التي قد تأخذ 3 بايت لكي تُمثَّل، فمثلًا، الحرف الإسباني ñ لا يأخذ بايتًا واحدًا وإنما ثلاثة بايتات.
	</li>
	<li>
		<code>TEXT(M)</code>: يُمثِّل هذا النوع الأعمدة ذات الطول الأقصى المقدّر 65535 محرفًا، لكن كما في نوع البيانات <code>VARCHAR(M)</code> سينقص طول التخزين الأقصى إذا استعملنا محارف تأخذ أكثر من بايت لتُمثَّل في الحاسوب. إذا حُدِّدَ <code>M</code> فسيُنشأ العمود بأصغر نوع بيانات التي يستطيع تخزين هذا العدد من المحارف.
	</li>
	<li>
		<code>MEDIUMTEXT(M)</code> و <code>LONGTEXT(M)</code> شبيهة بنوع البيانات <code>TEXT(M)</code> لكن الطول الأقصى المسموح هو 16777215 و 4294967295 محرفًا على التوالي وبالترتيب.
	</li>
</ul>
<h3 id="الوقت-والتاريخ">
	الوقت والتاريخ
</h3>

<ul>
<li>
		<code>DATE</code>: تمثيل التاريخ بصيغة <code>YYYY-MM-DD</code>.
	</li>
	<li>
		<code>TIME</code>: تمثيل الوقت بصيغة <code>HH:MM:SS.sss</code> (أي الساعة والدقيقة والثانية والملي ثانية).
	</li>
	<li>
		<code>DATETIME</code>: جمعٌ بين <code>DATE</code> و <code>TIME</code> بالصيغة <code>YYYY-MM-DD HH:MM:SS</code>.
	</li>
	<li>
		<code>TIMESTAMP</code>: تُستعمَل بصمة الوقت لتعريف اللحظة التي أضيف أو حُدِّث فيها سجلٌ (row) ما.<br>
		بعد اطلاعك على أنواع البيانات السابقة، فيمكن أن تستطيع الآن تحديد ما هو نوع البيانات الذي ستحتاج له لإسناده إلى عمودٍ معيّن في الجدول.<br>
		على سبيل المثال، يمكن أن يتسع اسم المستخدم بسهولة في عمودٍ بنوع البيانات <code>VARCHAR(50)</code>، لكن محتوى تدوينة سيحتاج إلى نوع <code>TEXT</code> (اختر قيمة <code>M</code> بما يلبي احتياجاتك).
	</li>
</ul>
<h2 id="إنشاء-جداول-فيها-مفاتيح-أساسية-وأجنبية">
	إنشاء جداول فيها مفاتيح أساسية وأجنبية
</h2>

<p>
	قبل أن نشرع في إنشاء جداول، فمن الضروري استيعاب مفهومين أساسيين عن قواعد البيانات العلائقية: المفتاح الأساسي (primary key) والمفتاح الأجنبي (foreign key).<br>
	يحتوي المفتاح الأساسي قيمةً تُمثِّلُ مُعرِّفًا فريدًا لكل سطرٍ أو سجلٍ (row أو record) في الجدول، لكن في المقابل يستعمل المفتاح الأجنبي للربط بين البيانات في جدولين، وللتحكم في البيانات التي يمكن تخزينها في الجدول الذي يحتوي على المفتاح الأجنبي. يُعتَبَر المفتاحان الأساسي والأجنبي قيمًا رقميةً (<code>INT</code>) عادةً.<br>
	لشرح هذا المفهوم عمليًا، فلنستخدم قاعدة بيانات <code>BookstoreDB</code> ونُنشِئ جدولين باسم <code>AuthorsTBL</code> و <code>BooksTBL</code>. تُشير <code>NOT NULL</code> إلى أنَّ الحقل المرتبط بها يتطلب قيمةً تختلف عن <code>NULL</code>.<br>
	يمكن أيضًا استعمال <code>AUTO_INCREMENT</code> لزيادة قيمة عمود المفتاح الرئيسي الرقمي بمقدار 1 عند إضافة سجل جديد إلى الجدول.
</p>

<pre class="ipsCode" id="ips_uid_706_10">
MariaDB [(none)]&gt; USE BookstoreDB;
Database changed
MariaDB [BookstoreDB]&gt; CREATE TABLE AuthorsTBL (
-&gt; AuthorID INT NOT NULL AUTO_INCREMENT,
-&gt; AuthorName VARCHAR(100),
-&gt; PRIMARY KEY(AuthorID)
-&gt; );
Query OK, 0 rows affected (0.05 sec)
MariaDB [BookstoreDB]&gt; CREATE TABLE BooksTBL (
-&gt; BookID INT NOT NULL AUTO_INCREMENT,
-&gt; BookName VARCHAR(100) NOT NULL,
-&gt; AuthorID INT NOT NULL,
-&gt; BookPrice DECIMAL(6,2) NOT NULL,
-&gt; BookLastUpdated TIMESTAMP,
-&gt; BookIsAvailable BOOLEAN,
-&gt; PRIMARY KEY(BookID),
-&gt; FOREIGN KEY (AuthorID) REFERENCES AuthorsTBL(AuthorID)
-&gt; );
Query OK, 0 rows affected (0.05 sec)
MariaDB [BookstoreDB]&gt; </pre>

<p>
	يمكننا الآن المتابعة وإضافة السجلات إلى جدولَي <code>AuthorsTBL</code> و <code>BooksTBL</code>.
</p>

<h2 id="تحديد-السجلات-وإضافتها-وتحديثها-وحذفها">
	تحديد السجلات وإضافتها وتحديثها وحذفها
</h2>

<p>
	علينا أولًا ملء الجدول <code>AuthorsTBL</code>، لكن لماذا؟ لأننا سنحتاج إلى وجود قيم في العمود <code>AuthorID</code> قبل إضافة سجلات إلى جدول <code>BooksTBL</code>.<br>
	نفِّذ الأمر الآتي من مِحَث MariaDB:
</p>

<pre class="ipsCode" id="ips_uid_706_12">
MariaDB [BookstoreDB]&gt; INSERT INTO AuthorsTBL (AuthorName) VALUES ('Agatha Christie'), ('Stephen King'), ('Paulo Coelho');</pre>

<p>
	بعدئذٍ سنُحدِّد جميع السجلات من جدول <code>AuthorsTBL</code>. تذكّر أننا نحتاج إلى <code>AuthorID</code> لكل سجل لإنشاء استعلام <code>INSERT</code> في جدول <code>BooksTBL</code>.<br>
	إذا أردتَ الحصول على سجلٍ وحيدٍ فقط، فاستعمل عبارة <code>WHERE</code> لكتابة شرط الذي يجب أن تُحقِّقه السجلات المُعادة. على سبيل المثال:
</p>

<pre class="ipsCode" id="ips_uid_706_14">
MariaDB [BookstoreDB]&gt; SELECT * FROM AuthorsTBL WHERE AuthorName='Agatha Christie';</pre>

<p>
	يمكنك عوضًا عن ذلك أن تحصل على جميع السجلات معًا:
</p>

<pre class="ipsCode" id="ips_uid_706_16">
MariaDB [BookstoreDB]&gt; SELECT * FROM AuthorsTBL;</pre>

<p>
	ناتج تنفيذ الطلبيتين السابقتين:
</p>

<pre class="ipsCode" id="ips_uid_706_18">
MariaDB [BookstoreDB]&gt; SELECT * FROM AuthorsTBL WHERE AuthorName='Agatha Christie';
+----------+-----------------+
| AuthorID | AuthorName      |
+----------+-----------------+
|        1 | Agatha Christie |
+----------+-----------------+
1 row in set (0.00 sec)
MariaDB [BookstoreDB]&gt; SELECT * FROM AuthorsTBL;
+----------+-----------------+
| AuthorID | AuthorName      |
+----------+-----------------+
|        1 | Agatha Christie |
|        2 | Stephen King    |
|        3 | Paulo Coelho    |
+----------+-----------------+
3 rows in set (0.00 sec)
MariaDB [BookstoreDB]&gt;</pre>

<p>
	لنُنشِئ الآن استعلام <code>INSERT</code> لجدول <code>BooksTBL</code>، وذلك عبر استخدام حقل <code>AuthorID</code> المناسب لمُطابقة مؤلف كل كتاب. القيمة 1 في حقل <code>BookIsAvaiable</code> تعني توافر الكتاب، بينما 0 تعني عكس ذلك:
</p>

<pre class="ipsCode" id="ips_uid_706_20">
MariaDB [BookstoreDB]&gt; INSERT INTO BooksTBL (BookName, AuthorID, BookPrice, BookIsAvailable)
-&gt; VALUES ('And Then There Were None', 1, 14.95, 1),
-&gt; ('The Man in the Brown Suit', 1, 23.99, 1),
-&gt; ('The Stand', 2, 35.99, 1),
-&gt; ('Pet Sematary', 2, 17.95, 0),
-&gt; ('The Green Mile', 2, 29.99, 1),
-&gt; ('The Alchemist', 3, 25, 1),
-&gt; ('By the River Piedra I Sat Down and Wept', 3, 18.95, 0);
Query OK, 7 rows affected (0.03 sec)
Records: 7  Duplicates: 0  Warnings: 0</pre>

<p>
	سنستخدم الآن <code>SELECT</code> لرؤية السجلات في جدول <code>BooksTBL</code> ثم سنُحدِّث عبر <code>UPDATE</code> سعر كتاب «The Alchemist» لمؤلفه Paulo Coelho ثم سنعرض السجلات (عبر <code>SELECT</code>) مرةً أخرى.<br>
	لاحظ كيف يعرض الحقل <code>BookLastUpdated</code> قيمةً مختلفةً، وكما شرحنا سابقًا، الحقل <code>TIMESTAMP</code> يُخزِّن الوقت الذي أُنشِئ أو حُدِّث فيه السجل.
</p>

<pre class="ipsCode" id="ips_uid_706_22">
MariaDB [BookstoreDB]&gt; SELECT * FROM BooksTBL;
+--------+-----------------------------------------+----------+-----------+---------------------+-----------------+
| BookID | BookName                                | AuthorID | BookPrice | BookLastUpdated     | BookIsAvailable |
+--------+-----------------------------------------+----------+-----------+---------------------+-----------------+
|      1 | And Then There Were None                |        1 |     14.95 | 2016-10-01 23:31:41 |               1 |
|      2 | The Man in the Brown Suit               |        1 |     23.99 | 2016-10-01 23:31:41 |               1 |
|      3 | The Stand                               |        2 |     35.99 | 2016-10-01 23:31:41 |               1 |
|      4 | Pet Sematary                            |        2 |     17.95 | 2016-10-01 23:31:41 |               0 |
|      5 | The Green Mile                          |        2 |     29.99 | 2016-10-01 23:31:41 |               1 |
|      6 | The Alchemist                           |        3 |     25.00 | 2016-10-01 23:31:41 |               1 |
|      7 | By the River Piedra I Sat Down and Wept |        3 |     18.95 | 2016-10-01 23:31:41 |               0 |
+--------+-----------------------------------------+----------+-----------+---------------------+-----------------+
7 rows in set (0.00 sec)
MariaDB [BookstoreDB]&gt; UPDATE BooksTBL SET BookPrice=22.75 WHERE BookID=6;
Query OK, 1 row affected (0.04 sec)
Rows matched: 1  Changed: 1  Warnings: 0
MariaDB [BookstoreDB]&gt; SELECT * FROM BooksTBL WHERE BookID=6;
+--------+---------------+----------+-----------+---------------------+-----------------+
| BookID | BookName      | AuthorID | BookPrice | BookLastUpdated     | BookIsAvailable |
+--------+---------------+----------+-----------+---------------------+-----------------+
|      6 | The Alchemist |        3 |     22.75 | 2016-10-01 23:35:00 |               1 |
+--------+---------------+----------+-----------+---------------------+-----------------+
1 row in set (0.00 sec)
MariaDB [BookstoreDB]&gt; </pre>

<p>
	لنفترض أننا نريد حذف أحد السجلات الذي لم يعد مفيدًا، فمثلًا سنحذف كتاب «The Alchemist» من جدول <code>BooksTBL</code>. يمكنك استخدام عبارة <code>DELETE</code> لفعل ذلك كما يلي:
</p>

<pre class="ipsCode" id="ips_uid_706_24">
MariaDB [BookstoreDB]&gt; DELETE FROM BooksTBL WHERE BookID=6;</pre>

<p>
	وكما في عبارة <code>UPDATE</code>، من المستحسن إجراء عملية <code>SELECT</code> أولًا لرؤية الحقول التي ستؤثر فيها عملية الحذف.<br>
	لا تنسَ أن تُضيف عبارة <code>WHERE</code> وشرطًا(<code>BookID=6</code>) لتحديد سجل مُعيّن لحذفه. وإلا فقد تصبح جميع سجلات جدولك معرضةً للحذف.<br>
	إذا أردتَ دمج حقلين (أو أكثر) معًا، فيمكنك استخدام عبارة <code>CONCAT</code>، فلنقل على سبيل المثال أننا نريد عرض ناتج يحتوي على عمودٍ فيه اسم الكتاب والمؤلف على الشكل الآتي «The Alchemist (Paulo Coelho)» ثم يليه عمودٌ فيه سعره.<br>
	هذا سيتطلب إجراء عملية <code>JOIN</code> بين جدولَي <code>AuthorsTBL</code> و <code>BooksTBL</code> في الحقل المشترك بينهما (ألا وهو <code>AuthorID</code>):
</p>

<pre class="ipsCode" id="ips_uid_706_26">
MariaDB [BookstoreDB]&gt; SELECT CONCAT(BooksTBL.BookName, ' (', AuthorsTBL.AuthorName, ')') AS Description, BooksTBL.BookPrice FROM AuthorsTBL JOIN BooksTBL ON AuthorsTBL.AuthorID = BooksTBL.AuthorID;</pre>

<p>
	وكما نرى، تسمح لنا عبارة <code>CONCAT</code> بدمج عدِّة تعبيرات نصية المفصول بينها بفاصلة. ستلاحظ أيضًا أننا استخدمنا اسمًا بديلًا وهو <code>Description</code> لعرض ناتج عملية دمج الحقلين.<br>
	هذا هو ناتج تنفيذ الاستعلام السابقة:
</p>

<pre class="ipsCode" id="ips_uid_706_28">
MariaDB [BookstoreDB]&gt; SELECT CONCAT(BooksTBL.BookName, ' (', AuthorsTBL.AuthorName, ')') AS Description, BooksTBL.BookPrice FROM AuthorsTBL JOIN BooksTBL ON AuthorsTBL.AuthorID = BooksTBL.AuthorID;
+--------------------------------------------------------+-----------+
| Description                                            | BookPrice |
+--------------------------------------------------------+-----------+
| And Then There Were None (Agatha Christie)             |     14.95 |
| The Man in the Brown Suit (Agatha Christie)            |     23.99 |
| The Stand (Stephen King)                               |     35.99 |
| Pet Sematary (Stephen King)                            |     17.95 |
| The Green Mile (Stephen King)                          |     29.99 |
| The Alchemist (Paulo Coelho)                           |     25.00 |
| By the River Piedra I Sat Down and Wept (Paulo Coelho) |     18.95 |
+--------------------------------------------------------+-----------+
7 rows in set (0.00 sec)</pre>

<h2 id="إنشاء-مستخدم-للوصول-إلى-قاعدة-بيانات-bookstoredb">
	إنشاء مستخدم للوصول إلى قاعدة بيانات BookstoreDB
</h2>

<p>
	لا أنصحك باستخدام المستخدم root لإجراء جميع عمليات معالجة البيانات، ولتجنب ذلك سنُنِشئ حساب مستخدم جديد (سنسميه <code>bookstoreuser</code>) ونُسنِد إليه جميع الامتيازات اللازمة لإدارة قاعدة البيانات <code>BookstoreDB</code>:
</p>

<pre class="ipsCode" id="ips_uid_706_30">
MariaDB [BookstoreDB]&gt; CREATE USER bookstoreuser@localhost IDENTIFIED BY 'tecmint';
Query OK, 0 rows affected (0.00 sec)
MariaDB [BookstoreDB]&gt; GRANT ALL PRIVILEGES ON  BookstoreDB.* to bookstoreuser@localhost;
Query OK, 0 rows affected (0.00 sec)
MariaDB [BookstoreDB]&gt; FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.00 sec)</pre>

<p>
	وجود حساب مستخدم منفصل ومخصص لكل قاعدة بيانات سيحمي كامل الخادوم إن حدث اختراقٌ لأحد الحسابات.
</p>

<h2 id="نصائح-إضافية-في-قواعد-mysql">
	نصائح إضافية في قواعد MySQL
</h2>

<p>
	لمسح الشاشة وإظهار مِحَث MariaDB فيها فقط، فأدخِل الأمر الآتي ثم اضغط على Enter:
</p>

<pre class="ipsCode" id="ips_uid_706_32">
MariaDB [BookstoreDB]&gt; \! clear</pre>

<p>
	نفِّذ الأمر الآتي لرؤية بنية أحد الجداول:
</p>

<pre class="ipsCode" id="ips_uid_706_34">
MariaDB [BookstoreDB]&gt; SHOW COLUMNS IN [TABLE NAME HERE ];</pre>

<p>
	لعرض الأعمدة الموجودة في جدول <code>BooksTBL</code> في قاعدة بياناتنا:
</p>

<pre class="ipsCode" id="ips_uid_706_36">
MariaDB [BookstoreDB]&gt; SHOW COLUMNS IN BooksTBL;
+-----------------+--------------+------+-----+-------------------+-----------------------------+
| Field           | Type         | Null | Key | Default           | Extra                       |
+-----------------+--------------+------+-----+-------------------+-----------------------------+
| BookID          | int(11)      | NO   | PRI | NULL              | auto_increment              |
| BookName        | varchar(100) | NO   |     | NULL              |                             |
| AuthorID        | int(11)      | NO   | MUL | NULL              |                             |
| BookPrice       | decimal(6,2) | NO   |     | NULL              |                             |
| BookLastUpdated | timestamp    | NO   |     | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP |
| BookIsAvailable | tinyint(1)   | YES  |     | NULL              |                             |
+-----------------+--------------+------+-----+-------------------+-----------------------------+
6 rows in set (0.02 sec)</pre>

<p>
	تفحص سريع لبنية الجدول سيكشف أنَّ الحقل <code>BookIsAvailable</code> يقبل القيم <code>NULL</code>. ولعدم رغبتنا في ذلك، فسنُعدِّل (<code>ALTER</code>) الجدول كالآتي:
</p>

<pre class="ipsCode" id="ips_uid_706_38">
MariaDB [BookstoreDB]&gt; ALTER TABLE BooksTBL MODIFY BookIsAvailable BOOLEAN NOT NULL;</pre>

<p>
	(تستطيع الآن عرض بنية الجدول مرةً أخرى، وستجد أنَّ كلمة <code>YES</code> الموجودة في عمود <code>Null</code> أصبحت <code>NO</code>).<br>
	أخيرًا، لعرض جميع قواعد البيانات في خادومك، تستطيع تنفيذ الأمر:
</p>

<pre class="ipsCode" id="ips_uid_706_40">
MariaDB [BookstoreDB]&gt; SHOW DATABASES;</pre>

<p>
	أو
</p>

<pre class="ipsCode" id="ips_uid_706_42">
MariaDB [BookstoreDB]&gt; SHOW SCHEMAS;</pre>

<p>
	الناتج الآتي يعرض مخرجات الأمر السابق بعد الدخول إلى مِحَث MariaDB عبر المستخدم <code>bookstoreuser</code> (لاحظ أنَّ هذا الحساب لا يستطيع «رؤية» أيّة قواعد بيانات ما عدا <code>BookstoreDB</code> و <code>information_schema</code> [المتوافرة لجميع المستخدمين]):
</p>

<pre class="ipsCode" id="ips_uid_706_44">
[root@TecMint ~]# mysql -u bookstoreuser -p
Enter password: 
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 3
Server version: 10.1.14-MariaDB MariaDB Server
Copyright (c) 2000, 2016, Oracle, MariaDB Corporation Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MariaDB [BookstoreDB]&gt; SHOW DATABASES;
+--------------------+
| Database           |
+--------------------+
| BookstoreDB        |
| information_schema |
+--------------------+
2 rows in set (0.00 sec)
MariaDB [BookstoreDB]&gt; SHOW SCHEMAS;
+--------------------+
| Database           |
+--------------------+
| BookstoreDB        |
| information_schema |
+--------------------+
2 rows in set (0.00 sec)</pre>

<h2 id="الخلاصة">
	الخلاصة
</h2>

<p>
	شرحنا في هذا الدرس كيفية إجراء عمليات على البيانات، إضافةً إلى إنشاء قاعدة بيانات، وجداولها، وتخصيص مستخدم لقاعدة البيانات، ثم رأينا فائدة بعض التلميحات التي تساعد في تسهيل إدارة قواعد البيانات عليك.<br>
	ترجمة -وبتصرّف- للمقال <a href="http://www.tecmint.com/learn-mysql-mariadb-for-beginners/" rel="external nofollow">Learn MySQL / MariaDB for Beginners – Part 1</a> لصاحبه Gabriel Cánepa.
</p>
]]></description><guid isPermaLink="false">297</guid><pubDate>Thu, 26 Jan 2017 11:52:00 +0000</pubDate></item><item><title>&#x643;&#x64A;&#x641; &#x62A;&#x62F;&#x64A;&#x631; &#x642;&#x648;&#x627;&#x639;&#x62F; &#x628;&#x64A;&#x627;&#x646;&#x627;&#x62A; MySQL &#x628;&#x627;&#x633;&#x62A;&#x62E;&#x62F;&#x627;&#x645; mysqladmin</title><link>https://academy.hsoub.com/devops/servers/databases/mysql/%D9%83%D9%8A%D9%81-%D8%AA%D8%AF%D9%8A%D8%B1-%D9%82%D9%88%D8%A7%D8%B9%D8%AF-%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-mysql-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-mysqladmin-r296/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2017_01/mysql-2.png.813e2f5654ef110d0b0c4de377dd5bfb.png" /></p>

<p id="كيف-تدير-قواعد-بيانات-mysql-باستخدام-mysqladmin">
	أداة <code>mysqladmin</code> هي أداةٌ سطريةٌ (أي تعمل من سطر الأوامر) تأتي مع خادوم MySQL ويستعملها مدراء قواعد البيانات لإجراء مهام أساسية لإدارة قواعد MySQL مثل ضبط كلمة مرور المستخدم root أو تغييرها، ومراقبة عمليات mysql وإعادة تحديث امتيازات المستخدمين والتحقق من حالة الخدمة …إلخ.
</p>

<p style="text-align: center;">
	<img alt="mysql-2.png" class="ipsImage ipsImage_thumbnailed" data-fileid="20835" data-unique="wf0q6rpk5" src="https://academy.hsoub.com/uploads/monthly_2017_01/mysql-2.png.6c574568809b53c9a3ec1a2385754b78.png"></p>

<p>
	<br>
	سنضع في هذا الدرس بعض أوامر <code>mysqladmin</code> المفيدة والمُستعمَلة من مدراء النظام أو مدراء قواعد البيانات يوميًا. يجب أن يكون خادوم MySQL مثبتًا على نظامك لإجراء هذه المهام.<br>
	إذا لم يكن خادوم MySQL مثبتًا على نظامك، أو كنتَ تستعمل إصدارًا قديمًا منه، فأنصحك بتثبيت أو تحديث نسختك كما ذكرنا في <a href="https://academy.hsoub.com/devops/servers/databases/%D8%AA%D8%AB%D8%A8%D9%8A%D8%AA-%D9%88%D8%A5%D8%B9%D8%AF%D8%A7%D8%AF-%D9%86%D8%B8%D8%A7%D9%85%D9%8A-%D8%A5%D8%AF%D8%A7%D8%B1%D8%A9-%D9%82%D9%88%D8%A7%D8%B9%D8%AF-%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-mysql-%D9%88postgresql-%D8%B9%D9%84%D9%89-%D8%A3%D9%88%D8%A8%D9%86%D8%AA%D9%88-r194/" rel="">هذه المقالة</a>.
</p>

<h2 id="1-كيفية-ضبط-كلمة-مرور-المستخدم-root-في-mysql">
	1. كيفية ضبط كلمة مرور المستخدم root في MySQL؟
</h2>

<p>
	إذا كانت لديك نسخةٌ حديثةُ التثبيت من خادوم MySQL، فلن تحتاج إلى استخدام كلمة مرور للاتصال بها عبر المستخدم root، لكن ذلك ليس آمنًا، وأنصحك بضبط كلمة مرور له، وذلك بتنفيذ الأمر الآتي:
</p>

<pre class="ipsCode" id="ips_uid_5804_7">
# mysqladmin -u root password YOURNEWPASSWORD</pre>

<h2 id="2-كيفية-تغيير-كلمة-مرور-المستخدم-root">
	2. كيفية تغيير كلمة مرور المستخدم root؟
</h2>

<p>
	إذا أردتَ تحديث أو تغيير كلمة مرور المستخدم root في قواعد بيانات MySQL، فيمكنك الاستعانة بالأمر الآتي. لنفترض مثلًا أنَّ كلمة مرورك القديمة هي 123456 وأردتَ الآن تغييرها إلى كلمةٍ أخرى ولتكن xyz123:
</p>

<pre class="ipsCode" id="ips_uid_5804_9">
# mysqladmin -u root -p123456 password 'xyz123'</pre>

<h2 id="3-كيفية-التحقق-إذا-كان-خادوم-mysql-يعمل">
	3. كيفية التحقق إذا كان خادوم MySQL يعمل؟
</h2>

<p>
	استعمل الأمر الآتي لتعرف إن كان خادوم MySQL يعمل أم لا:
</p>

<pre class="ipsCode" id="ips_uid_5804_11">
# mysqladmin -u root -p ping
Enter password:
mysqld is alive</pre>

<h2 id="4-كيف-أعرف-إصدار-mysql-الذي-أعمل-عليه">
	4. كيف أعرف إصدار MySQL الذي أعمل عليه؟
</h2>

<p>
	الأمر الآتي سيُظهِر إصدار MySQL المُثبَّت على خادومك، إضافةً إلى حالته:
</p>

<pre class="ipsCode" id="ips_uid_5804_13">
# mysqladmin -u root -p version
Enter password:
mysqladmin  Ver 8.42 Distrib 5.5.28, for Linux on i686
Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Server version          5.5.28
Protocol version        10
Connection              Localhost via UNIX socket
UNIX socket             /var/lib/mysql/mysql.sock
Uptime:                 7 days 14 min 45 sec
Threads: 2  Questions: 36002  Slow queries: 0  Opens: 15  Flush tables: 1  Open tables: 8  Queries per second avg: 0.059</pre>

<h2 id="5-كيف-أعرف-ما-هي-حالة-خادوم-mysql-الآن">
	5. كيف أعرف ما هي حالة خادوم MySQL الآن؟
</h2>

<p>
	يمكن أن يُظهِر الأمر <code>mysqladmin</code> حالة uptime بالإضافة إلى عدد الخيوط (threads) وإحصائيات عن الاستعلامات:
</p>

<pre class="ipsCode" id="ips_uid_5804_16">
# mysqladmin -u root -ptmppassword status
Enter password:
Uptime: 606704  Threads: 2  Questions: 36003  Slow queries: 0  Opens: 15  Flush tables: 1  Open tables: 8  Queries per second avg: 0.059</pre>

<h2 id="6-كيفية-التحقق-من-حالة-جميع-متغيرات-خادوم-mysql-وقيمها">
	6. كيفية التحقق من حالة جميع متغيرات خادوم MySQL وقيمها؟
</h2>

<p>
	استخدم الخيار <code>extended-status</code> لأمر <code>mysqladmin</code> لرؤية حالة جميع متغيرات خادوم MySQL والقيم المرتبطة بها. يجب أن تكون المخرجات شبيهةً بما يلي:
</p>

<pre class="ipsCode" id="ips_uid_5804_18">
# mysqladmin -u root -p extended-status
Enter password:
+------------------------------------------+-------------+
| Variable_name                            | Value       |
+------------------------------------------+-------------+
| Aborted_clients                          | 3           |
| Aborted_connects                         | 3           |
| Binlog_cache_disk_use                    | 0           |
| Binlog_cache_use                         | 0           |
| Binlog_stmt_cache_disk_use               | 0           |
| Binlog_stmt_cache_use                    | 0           |
| Bytes_received                           | 6400357     |
| Bytes_sent                               | 2610105     |
| Com_admin_commands                       | 3           |
| Com_assign_to_keycache                   | 0           |
| Com_alter_db                             | 0           |
| Com_alter_db_upgrade                     | 0           |
| Com_alter_event                          | 0           |
| Com_alter_function                       | 0           |
| Com_alter_procedure                      | 0           |
| Com_alter_server                         | 0           |
| Com_alter_table                          | 0           |
| Com_alter_tablespace                     | 0           |
+------------------------------------------+-------------+</pre>

<h2 id="7-كيفية-معرفة-قيم-جميع-المتغيرات-المفعلة-لخادوم-mysql">
	7. كيفية معرفة قيم جميع المتغيرات المُفعّلة لخادوم MySQL؟
</h2>

<p>
	لرؤية جميع القيم التي تعمل حاليًا في خادوم MySQL، أدخِل الأمر الآتي:
</p>

<pre class="ipsCode" id="ips_uid_5804_20">
# mysqladmin  -u root -p variables
Enter password:
+---------------------------------------------------+----------------------------------------------+
| Variable_name                                     | Value                                        |
+---------------------------------------------------+----------------------------------------------+
| auto_increment_increment                          | 1                                            |
| auto_increment_offset                             | 1                                            |
| autocommit                                        | ON                                           |
| automatic_sp_privileges                           | ON                                           |
| back_log                                          | 50                                           |
| basedir                                           | /usr                                         |
| big_tables                                        | OFF                                          |
| binlog_cache_size                                 | 32768                                        |
| binlog_direct_non_transactional_updates           | OFF                                          |
| binlog_format                                     | STATEMENT                                    |
| binlog_stmt_cache_size                            | 32768                                        |
| bulk_insert_buffer_size                           | 8388608                                      |
| character_set_client                              | latin1                                       |
| character_set_connection                          | latin1                                       |
| character_set_database                            | latin1                                       |
| character_set_filesystem                          | binary                                       |
| character_set_results                             | latin1                                       |
| character_set_server                              | latin1                                       |
| character_set_system                              | utf8                                         |
| character_sets_dir                                | /usr/share/mysql/charsets/                   |
| collation_connection                              | latin1_swedish_ci                            |
+---------------------------------------------------+----------------------------------------------+</pre>

<h2 id="8-كيفية-التحقق-من-جميع-العمليات-التي-يستخدمها-خادوم-mysql">
	8. كيفية التحقق من جميع العمليات التي يستخدمها خادوم MySQL؟
</h2>

<p>
	الأمر الآتي سيعرض جميع العمليات التي تستعملها استعلامات قواعد بيانات MySQL:
</p>

<pre class="ipsCode" id="ips_uid_5804_22">
# mysqladmin -u root -p processlist
Enter password:
+-------+---------+-----------------+---------+---------+------+-------+------------------+
| Id    | User    | Host            | db      | Command | Time | State | Info             |
+-------+---------+-----------------+---------+---------+------+-------+------------------+
| 18001 | rsyslog | localhost:38307 | rsyslog | Sleep   | 5590 |       |                  |
| 18020 | root    | localhost       |         | Query   | 0    |       | show processlist |
+-------+---------+-----------------+---------+---------+------+-------+------------------+</pre>

<h2 id="9-كيفية-إنشاء-قاعدة-بيانات-على-خادوم-mysql">
	9. كيفية إنشاء قاعدة بيانات على خادوم MySQL؟
</h2>

<p>
	استخدم الأمر الآتي لإنشاء قاعدة بيانات جديدة في MySQL:
</p>

<pre class="ipsCode" id="ips_uid_5804_24">
# mysqladmin -u root -p create databasename
Enter password:</pre>

<p>
	للتحقق من إنشائها:
</p>

<pre class="ipsCode" id="ips_uid_5804_26">
# mysql -u root -p
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 18027
Server version: 5.5.28 MySQL Community Server (GPL) by Remi
Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql&gt; show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| databasename       |
| mysql              |
| test               |
+--------------------+
8 rows in set (0.01 sec)
mysql&gt;</pre>

<h2 id="10-كيفية-حذف-قاعدة-بيانات-في-خادوم-mysql">
	10. كيفية حذف قاعدة بيانات في خادوم MySQL؟
</h2>

<p>
	لحذف قاعدة بيانات في خادوم MySQL، فأدخِل الأمر الآتي. سيُطلَب منك الموافقة على ذلك بكتابة الحرف <code>y</code>:
</p>

<pre class="ipsCode" id="ips_uid_5804_28">
# mysqladmin -u root -p drop databasename
Enter password:
Dropping the database is potentially a very bad thing to do.
Any data stored in the database will be destroyed.
Do you really want to drop the 'databasename' database [y/N] y
Database "databasename" dropped</pre>

<h2 id="11-كيفية-إعادة-تحميل-أو-إعادة-تحديث-الامتيازات-في-mysql">
	11. كيفية إعادة تحميل أو إعادة تحديث الامتيازات في MySQL؟
</h2>

<p>
	الأمر <code>reload</code> سيطلب من الخادوم إعادة تحميل جداول الامتيازات، بينما الأمر <code>refresh</code> سيؤدي إلى إعادة قراءة جميع الجداول وإعادة فتح ملفات التسجيل (log files):
</p>

<pre class="ipsCode" id="ips_uid_5804_30">
# mysqladmin -u root -p reload;
# mysqladmin -u root -p refresh</pre>

<h2 id="12-كيفية-إيقاف-خادوم-mysql-بأمان">
	12. كيفية إيقاف خادوم MySQL بأمان؟
</h2>

<p>
	لإيقاف خادوم MySQL إيقافًا آمنًا، فاكتب الأمر الآتي:
</p>

<pre class="ipsCode" id="ips_uid_5804_32">
mysqladmin -u root -p shutdown
Enter password:</pre>

<p>
	أو يمكنك استخدام الأمرين الآتيين لتشغيل أو إيقاف خادوم MySQL:
</p>

<pre class="ipsCode" id="ips_uid_5804_34">
# /etc/init.d/mysqld stop
# /etc/init.d/mysqld start</pre>

<h2 id="13-بعض-أوامر-التنظيف">
	13. بعض أوامر «التنظيف»
</h2>

<p>
	هذه بعض أوامر التنظيف (flush) مع شرحٍ لها:
</p>

<ul>
<li>
		<code>flush-hosts</code>: حذف جميع معلومات المُضيف من التخزين المؤقت.
	</li>
	<li>
		<code>flush-tables</code>: «تنظيف» جميع الجداول.
	</li>
	<li>
		<code>flush-threads</code>: تنظيف التخزين المؤقت للخيوط (threads).
	</li>
	<li>
		<code>flush-logs</code>: تنظيف السجلات.
	</li>
	<li>
		<code>flush-privileges</code>: إعادة تحميل جداول الامتيازات (مثل <code>reload</code>).
	</li>
	<li>
		<code>flush-status</code>: مسح متغيرات الحالة (status variables).
	</li>
	<li>
		<pre class="ipsCode" id="ips_uid_5804_36">
# mysqladmin -u root -p flush-hosts
# mysqladmin -u root -p flush-tables
# mysqladmin -u root -p flush-threads
# mysqladmin -u root -p flush-logs
# mysqladmin -u root -p flush-privileges
# mysqladmin -u root -p flush-status</pre>

		<p>
			 
		</p>
	</li>
</ul>
<h2 id="14-كيفية-قتل-عمليات-عملاء-mysql-المتوقفة">
	14. كيفية «قتل» عمليات عملاء MySQL المتوقفة؟
</h2>

<p>
	يمكنك استخدام الأمر الآتي للتعرف على عمليات عملاء MySQL المتوقفة (sleeping):
</p>

<pre class="ipsCode" id="ips_uid_5804_38">
# mysqladmin -u root -p processlist
Enter password:
+----+------+-----------+----+---------+------+-------+------------------+
| Id | User | Host      | db | Command | Time | State | Info             |
+----+------+-----------+----+---------+------+-------+------------------+
| 5  | root | localhost |    | Sleep   | 14   |       |                  |
| 8  | root | localhost |    | Query   | 0    |       | show processlist |
+----+------+-----------+----+---------+------+-------+------------------+</pre>

<p>
	يمكنك الآن تشغيل الأمر الآتي مع استخدام الخيار <code>kill</code> متبوعًا برقم العملية كما يلي:
</p>

<pre class="ipsCode" id="ips_uid_5804_40">
# mysqladmin -u root -p kill 5
Enter password:
+----+------+-----------+----+---------+------+-------+------------------+
| Id | User | Host      | db | Command | Time | State | Info             |
+----+------+-----------+----+---------+------+-------+------------------+
| 12 | root | localhost |    | Query   | 0    |       | show processlist |
+----+------+-----------+----+---------+------+-------+------------------+</pre>

<p>
	أما إذا أردت «قتل» (اصطلاح «قتل» [kill] في يونكس يعني إيقاف العملية قسريًا) أكثر من عملية معًا، فافصل بين أرقام العمليات بفاصلة كما في المثال الآتي:
</p>

<pre class="ipsCode" id="ips_uid_5804_42">
# mysqladmin -u root -p kill 5,10</pre>

<h2 id="15-كيفية-تشغيل-أكثر-من-أمر-لأداة-mysqladmin-معا">
	15. كيفية تشغيل أكثر من أمر لأداة mysqladmin معًا؟
</h2>

<p>
	إذا أردت تشغيل أكثر من أمر <code>mysqladmin</code> معًا فيمكنك فعل ذلك بذكرها بعضها تلو بعض كالآتي:
</p>

<pre class="ipsCode" id="ips_uid_5804_44">
# mysqladmin  -u root -p processlist status version
Enter password:
+----+------+-----------+----+---------+------+-------+------------------+
| Id | User | Host      | db | Command | Time | State | Info             |
+----+------+-----------+----+---------+------+-------+------------------+
| 8  | root | localhost |    | Query   | 0    |       | show processlist |
+----+------+-----------+----+---------+------+-------+------------------+
Uptime: 3801  Threads: 1  Questions: 15  Slow queries: 0  Opens: 15  Flush tables: 1  Open tables: 8  Queries per second avg: 0.003
mysqladmin  Ver 8.42 Distrib 5.5.28, for Linux on i686
Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Server version          5.5.28
Protocol version        10
Connection              Localhost via UNIX socket
UNIX socket             /var/lib/mysql/mysql.sock
Uptime:                 1 hour 3 min 21 sec
Threads: 1  Questions: 15  Slow queries: 0  Opens: 15  Flush tables: 1  Open tables: 8  Queries per second avg: 0.003</pre>

<h2 id="16-كيفية-الاتصال-بخادوم-mysql-بعيد">
	16. كيفية الاتصال بخادوم MySQL بعيد
</h2>

<p>
	للاتصال بخادوم MySQL بعيد فاستخدام الخيار <code>‎-h</code> (أي host، ويعني المضيف) وبعده عنوان IP للخادوم البعيد:
</p>

<pre class="ipsCode" id="ips_uid_5804_46">
# mysqladmin  -h 172.16.25.126 -u root -p</pre>

<h2 id="17-كيفية-تنفيذ-أمر-على-خادوم-mysql-بعيد">
	17. كيفية تنفيذ أمر على خادوم MySQL بعيد
</h2>

<p>
	لنقل أنك تريد معرفة حالة (status) خادوم MySQL بعيد، فسيكون الأمر حينئذٍ كالآتي:
</p>

<pre class="ipsCode" id="ips_uid_5804_48">
# mysqladmin  -h 172.16.25.126 -u root -p status</pre>

<h2 id="18-تشغيل-وإيقاف-استنساخ-mysql-على-خادوم-ثانوي">
	18. تشغيل وإيقاف استنساخ MySQL على خادوم ثانوي
</h2>

<p>
	استخدم الأمرين الآتيين لتشغيل أو إيقاف استنساخ MySQL (أي MySQL replication):
</p>

<pre class="ipsCode" id="ips_uid_5804_50">
# mysqladmin  -u root -p start-slave
# mysqladmin  -u root -p stop-slave</pre>

<h2 id="19-كيفية-تخزين-معلومات-التنقيح-في-mysql-إلى-السجلات">
	19. كيفية تخزين معلومات التنقيح في MySQL إلى السجلات
</h2>

<p>
	معلومات التنقيح هي المعلومات التي تخبرنا ما هو استخدام الذاكرة ومعلومات متفرقة عن الاستعلامات، ويمكننا كتابتها إلى ملف سجل MySQL باستخدام الأمر الآتي:
</p>

<pre class="ipsCode" id="ips_uid_5804_52">
# mysqladmin  -u root -p debug
Enter password:</pre>

<h2 id="20-كيفية-رؤية-الخيارات-المتاحة-للاستخدام-في-mysqladmin">
	20. كيفية رؤية الخيارات المتاحة للاستخدام في mysqladmin
</h2>

<p>
	لمعرفة المزيد من خيارات الأمر <code>mysqladmin</code> وطريقة استخدامه، فاطلع على المساعدة التي تظهر بكتابة الأمر الآتي، والذي سيعرض قائمة بالخيارات المتوافرة:
</p>

<pre class="ipsCode" id="ips_uid_5804_54">
# mysqladmin --help</pre>

<p>
	حاولتُ قدر المستطاع أن أُضمِّن أغلبية أوامر <code>mysqladmin</code> مع أمثلةٍ عنها في هذا الدرس، لكن لا مانع من محاولة استكشاف غيرها، وربما تشاركنا بها في التعليقات.<br>
	ترجمة -وبتصرّف- للمقال <a href="http://www.tecmint.com/mysqladmin-commands-for-database-administration-in-linux/" rel="external nofollow">‎20 MySQL (Mysqladmin) Commands for Database Administration in Linux</a> لصاحبه Ravi Saive
</p>
]]></description><guid isPermaLink="false">296</guid><pubDate>Wed, 30 Nov 2016 11:05:00 +0000</pubDate></item><item><title>&#x645;&#x62F;&#x62E;&#x644; &#x625;&#x644;&#x649; &#x623;&#x647;&#x645; &#x627;&#x644;&#x627;&#x633;&#x62A;&#x639;&#x644;&#x627;&#x645;&#x627;&#x62A; (queries) &#x641;&#x64A; MySQL</title><link>https://academy.hsoub.com/devops/servers/databases/mysql/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-%D8%A3%D9%87%D9%85-%D8%A7%D9%84%D8%A7%D8%B3%D8%AA%D8%B9%D9%84%D8%A7%D9%85%D8%A7%D8%AA-queries-%D9%81%D9%8A-mysql-r295/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2017_01/mysql-001.png.2fff815c80acb93b92217d6b20f0aab6.png" /></p>

<p id="مدخل-إلى-أهم-الاستعلامات-queries-في-mysql">
	قاعدة البيانات هي بُنيةٌ هيكليةٌ تحتوي على مجموعة من البيانات المُخزَّنة إلكترونيًا؛ وكان مفهوم قواعد البيانات معروفًا لدى أسلافنا قبل وجود الحواسيب، لكن إنشاء وصيانة تلك القواعد كان أمرًا شاقًا ومملًا. فلنقل أنَّ لدينا قاعدة بيانات فيها 100 صفحة، وأردتَ أن تبحث عن جميع الموظفين الذين يتقاضون أقل من 50 ألف دولار سنويًا، فتخيّل مدى صعوبة الأمر ومقدار الوقت الذي سيستغرقه في ذاك الحين.
</p>

<p style="text-align: center;">
	<img alt="mysql-001.png" class="ipsImage ipsImage_thumbnailed" data-fileid="20834" data-unique="9g1oq9qys" src="https://academy.hsoub.com/uploads/monthly_2017_01/mysql-001.png.0f9b0bb2955d7a7185f73062a36a116d.png"></p>

<p>
	<br>
	أما حاليًا، فأنت تصادف قواعد البيانات في كل مكان، إذ تعمل ملايين قواعد البيانات في أنحاء العالم لتخزين والحصول على أي نوع من أنواع البيانات كالبيانات العسكرية وسجلات الموظفين أو حتى مواقع الويب وتقنياتها.<br>
	تُصنّف قواعد البيانات عمومًا على أنها جزءٌ من «السند الخلفي» (back-end)، وذلك لعدم ظهورها للمستخدم النهائي ولعدم تعامل المستخدم معها مباشرةً. إذ تعمل قواعد البيانات مع لغةٍ برمجيةٍ مثل PHP أو VB أو ASP.NET وتطلب تلك اللغات من قواعد البيانات إجراء عملية ما.<br>
	تتوافر عدِّة خواديم قواعد بيانات وعملاءٍ لها مثل Oracle و MySQL و MySQLi و MariaDB و MongoDB …إلخ. تتشابه طريقة التعامل مع هذه البيانات، والبنية اللغوية لأوامرها شبه متماثلة، واحتراف التعامل مع إحداها يعني أنَّك ستستطيع التحكم بأريحية مع البقية، وعملية تعلم كتابة الاستعلامات (queries) هي عملية سهلة وممتعة.<br>
	لنبدأ ببعض الاستعلامات البسيطة على قواعد البيانات؛ وسنستخدم قواعد MySQL التي تأتي مع أغلبية توزيعات لينُكس افتراضيًا، وتستطيع بسهولة تثبيتها من مستودعات توزيعتك إن لم تكن مثبتةً لديك.<br>
	لكن ربما ينتابك فضولٌ حول معنى «استعلام» (Query)، فبأبسط الكلمات: هي شيفرةٌ بسيطةٌ (أو أمر) تُرسَل إلى قواعد البيانات للحصول على النتيجة المطلوبة.
</p>

<h2 id="تثبيت-قواعد-بيانات-mysql">
	تثبيت قواعد بيانات MySQL
</h2>

<p>
	يمكنك استخدام مديرَي الحزم <code>yum</code> أو <code>apt</code> لتثبيت قواعد بيانات MySQL:
</p>

<pre class="ipsCode" id="ips_uid_657_7">
# yum install mysql mysql-client mysql-server  (on Yum based Systems)
# apt-get install mysql mysql-client mysql-server (on Apt based Systems)</pre>

<h2 id="تشغيل-خادوم-mysql">
	تشغيل خادوم MySQL
</h2>

<p>
	تستطيع تشغيل خدمة MySQL كالآتي:
</p>

<pre class="ipsCode" id="ips_uid_657_9">
# service mysqld start</pre>

<p>
	أو:
</p>

<pre class="ipsCode" id="ips_uid_657_11">
# service mysql start</pre>

<p>
	أذكِّرك أنَّ رمز <code>#</code> في بداية السطر يعني أنَّ عليك تنفيذ الأمر بامتيازات الجذر.<br>
	سيُطلَب منك أثناء تثبيت قاعدة بيانات <code>MySQL</code> إعداد كلمة مرور لحساب المدير فيها… بعدئذٍ ستتمكن من الوصول إلى مِحَث (prompt، أي المكان الذي تكتب فيه الأوامر) MySQL بتنفيذك للأمر الآتي:
</p>

<pre class="ipsCode" id="ips_uid_657_13">
# mysql -u root -p</pre>

<p>
	ضع اسم المستخدم الذي ضبطته بدلًا من <code>root</code>، وأدخِل كلمة مرورك عند طلبها، فإذا كانت معلومات الدخول صحيحةً، فيمكنك أن تشاهد مِحَث MySQL مباشرةً:
</p>

<pre class="ipsCode" id="ips_uid_657_15">
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 195 
Server version: 5.5.31-0+wheezy1 (Debian) 
Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. 
Oracle is a registered trademark of Oracle Corporation and/or its affiliates. 
Other names may be trademarks of their respective owners. 
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
Mysql&gt;</pre>

<p>
	تستطيع الآن البدء بتنفيذ الاستعلامات وتعلم إنشاء الاستعلامات.
</p>

<h2 id="إنشاء-قاعدة-بيانات">
	إنشاء قاعدة بيانات
</h2>

<p>
	سنُنشِئ الآن قاعدة بيانات باسم <code>tecmint</code> كالتّالي:
</p>

<pre class="ipsCode" id="ips_uid_657_17">
mysql&gt; create database tecmint ;
Query OK, 1 row affected (0.02 sec) 
mysql&gt;</pre>

<p>
	ظهر عندنا أنَّ الاستعلام السابق قد نُفِّذَ تنفيذًا سليمًا، وهذا يعني أنَّ قاعدة البيانات قد أُنشِئَت. يمكنك التحقق من وجود قاعدة البيانات الجديدة بتنفيذ الاستعلام الآتي:
</p>

<pre class="ipsCode" id="ips_uid_657_19">
mysql&gt; show databases; 
+--------------------+
| Database           | 
+--------------------+ 
| information_schema | 
| mysql              | 
| performance_schema | 
| tecmint            | 
| test               | 
+--------------------+ 
9 rows in set (0.00 sec) 
mysql&gt;</pre>

<p>
	لاحظ وجود قاعدة البيانات في مخرجات الاستعلام أعلاه.
</p>

<h2 id="اختيار-قاعدة-البيانات">
	اختيار قاعدة البيانات
</h2>

<p>
	علينا قبل إجراء الاستعلامات على إحدى قواعد البيانات أن نختارها، وذلك باستخدام التعليمة <code>use</code> كما يلي:
</p>

<pre class="ipsCode" id="ips_uid_657_21">
mysql&gt; use tecmint;
Database changed
mysql&gt;</pre>

<h2 id="إنشاء-الجداول-في-mysql">
	إنشاء الجداول في MySQL
</h2>

<p>
	لنقل أننا نريد إنشاء جدول باسم <code>minttec</code> في قاعدة البيانات وفيه ثلاثة حقول:
</p>

<pre class="ipsCode" id="ips_uid_657_23">
mysql&gt; CREATE TABLE minttec (
-&gt; id Int(3), 
-&gt; first_name Varchar (15), 
-&gt; email Varchar(20) 
-&gt; ); 
Query OK, 0 rows affected (0.08 sec) 
mysql&gt;</pre>

<p>
	لاحظ أنَّ الاستعلام السابق قد أعاد <code>OK</code> مما يعني أنَّ الجدول قد أُنشِئ دون أخطاء. نفِّذ الاستعلام الآتي للتحقق من إنشاء الجدول:
</p>

<pre class="ipsCode" id="ips_uid_657_25">
mysql&gt; show tables; 
+-------------------+ 
| Tables_in_tecmint | 
+-------------------+ 
| minttec           | 
+-------------------+ 
1 row in set (0.00 sec) 
mysql&gt;</pre>

<p>
	جيد، كل شيء يسير كما ينبغي. يمكننا أن نُطالِع الأعمدة التي أنشأتها في جدول <code>minttec</code> كما يلي:
</p>

<pre class="ipsCode" id="ips_uid_657_27">
mysql&gt; show columns from minttec; 
+------------+-------------+------+-----+---------+-------+ 
| Field      | Type        | Null | Key | Default | Extra | 
+------------+-------------+------+-----+---------+-------+ 
| id         | int(3)      | YES  |     | NULL    |       | 
| first_name | varchar(15) | YES  |     | NULL    |       | 
| email      | varchar(20) | YES  |     | NULL    |       | 
+------------+-------------+------+-----+---------+-------+ 
3 rows in set (0.00 sec)
mysql&gt;</pre>

<p>
	سأخبرك الآن عن أنواع البيانات الموجودة في الجدول السابق ومعانيها:<br>
	- <code>int</code>: عدد صحيح.<br>
	- <code>varchar</code>: سلسلة من المحارف التي لا يتجاوز طولها الرقم المُعرَّف. القيمة الرقمية التي تأتي بعد النوع هي «طول» الحقل الذي ستُخزَّن فيه البيانات.<br>
	لنقل الآن أننا نريد إضافة عمود جديد باسم <code>last_name</code> بعد العمود <code>first_name</code> سنقوم بذلك على النّحو التّالي:
</p>

<pre class="ipsCode" id="ips_uid_657_29">
mysql&gt; ALTER TABLE minttec ADD last_name varchar (20) AFTER first_name; 
Query OK, 0 rows affected (0.16 sec)
Records: 0  Duplicates: 0  Warnings: 0</pre>

<p>
	ثم سنتحقق من أعمدة الجدول:
</p>

<pre class="ipsCode" id="ips_uid_657_31">
mysql&gt; show cسolumns from minttec; 
+------------+-------------+------+-----+---------+-------+ 
| Field      | Type        | Null | Key | Default | Extra | 
+------------+-------------+------+-----+---------+-------+ 
| id         | int(3)      | YES  |     | NULL    |       | 
| first_name | varchar(15) | YES  |     | NULL    |       | 
| last_name  | varchar(20) | YES  |     | NULL    |       | 
| email      | varchar(20) | YES  |     | NULL    |       | 
+------------+-------------+------+-----+---------+-------+ 
4 rows in set (0.00 sec) 
mysql&gt;</pre>

<h2 id="إضافة-أعمدة-في-mysql">
	إضافة أعمدة في MySQL
</h2>

<p>
	سنضيف الآن عمودًا باسم <code>country</code> بعد العمود <code>email</code> كالتّالي:
</p>

<pre class="ipsCode" id="ips_uid_657_33">
mysql&gt; ALTER TABLE minttec ADD country varchar (15) AFTER email; 
Query OK, 0 rows affected (0.16 sec) 
Records: 0  Duplicates: 0  Warnings: 0 
mysql&gt;</pre>

<p>
	لنتحقق من إضافة العمود:
</p>

<pre class="ipsCode" id="ips_uid_657_35">
mysql&gt; show columns from minttec; 
+------------+-------------+------+-----+---------+-------+ 
| Field      | Type        | Null | Key | Default | Extra | 
+------------+-------------+------+-----+---------+-------+
| id         | int(3)      | YES  |     | NULL    |       | 
| first_name | varchar(15) | YES  |     | NULL    |       | 
| last_name  | varchar(20) | YES  |     | NULL    |       | 
| email      | varchar(20) | YES  |     | NULL    |       | 
| country    | varchar(15) | YES  |     | NULL    |       | 
+------------+-------------+------+-----+---------+-------+
5 rows in set (0.00 sec) 
mysql&gt;</pre>

<h2 id="إضافة-قيمة-إلى-الحقول">
	إضافة قيمة إلى الحقول
</h2>

<p>
	ماذا لو أردنا إضافة قيم إلى حقول الجدول؟ سنقوم بذلك كالتّالي:
</p>

<pre class="ipsCode" id="ips_uid_657_37">
mysql&gt; INSERT INTO minttec VALUES ('1' , 'Ravi' , 'Saive' , 'raivsaive@xyz.com' , 'India' );
Query OK, 1 row affected (0.02 sec) 
mysql&gt;</pre>

<p>
	ماذا عن إضافة أكثر من قيمة واحدة في آنٍ واحد:
</p>

<pre class="ipsCode" id="ips_uid_657_39">
mysql&gt; INSERT INTO minttec VALUES ('2' , 'Narad' , 'Shrestha' , 'narad@xyz.com' , 'India' ), ('3' , 'user' , 'singh' , 'user@xyz.com' , 'Aus' ), ('4' , 'tecmint' , '[dot]com' , 'tecmint@gmail.com' , 'India' );
Query OK, 3 rows affected (0.05 sec) 
Records: 3  Duplicates: 0  Warnings: 0</pre>

<p>
	سنتحقق من إدخال المعلومات السابقة في الجدول:
</p>

<pre class="ipsCode" id="ips_uid_657_41">
mysql&gt; select * from minttec; 
+------+------------+-----------+-------------------+---------+ 
| id   | first_name | last_name | email             | country | 
+------+------------+-----------+-------------------+---------+ 
|    1 | Ravi       | Saive     | raivsaive@xyz.com | India   | 
|    2 | Narad      | Shrestha  | narad@xyz.com     | India   | 
|    3 | user       | singh     | user@xyz.com      | Aus     | 
|    4 | tecmint    | [dot]com  | tecmint@gmail.com | India   | 
+------+------------+-----------+-------------------+---------+ 
4 rows in set (0.00 sec)
mysql&gt;</pre>

<h2 id="حذف-قيم-في-حقول-الجدول">
	حذف قيم في حقول الجدول
</h2>

<p>
	لنقل أنَّ المُدخَلة الثالثة في الناتج السابق لم تكن صحيحةً ونريد أن نحذفها:
</p>

<pre class="ipsCode" id="ips_uid_657_43">
mysql&gt; DELETE FROM minttec WHERE id = 3;
Query OK, 1 row affected (0.02 sec)</pre>

<p>
	التحقق من تنفيذ الاستعلام السابق:
</p>

<pre class="ipsCode" id="ips_uid_657_45">
mysql&gt; select * from minttec;
+------+------------+-----------+-------------------+---------+ 
| id   | first_name | last_name | email             | country | 
+------+------------+-----------+-------------------+---------+
|    1 | Ravi       | Saive     | raivsaive@xyz.com | India   | 
|    2 | Narad      | Shrestha  | narad@xyz.com     | India   | 
|    4 | tecmint    | [dot]com  | tecmint@gmail.com | India   | 
+------+------------+-----------+-------------------+---------+
3 rows in set (0.00 sec)</pre>

<h2 id="تحديث-قيم-في-حقول-الجدول">
	تحديث قيم في حقول الجدول
</h2>

<p>
	لنفترض أننا نريد تعديل السجل ذي المُعرِّف 4 (أي <code>id=4</code>):
</p>

<pre class="ipsCode" id="ips_uid_657_47">
mysql&gt; UPDATE minttec SET id = 3 WHERE first_name = 'tecmint'; 
Query OK, 1 row affected (0.02 sec)
Rows matched: 1  Changed: 1  Warnings: 0
mysql&gt;</pre>

<p>
	لاحظ أنَّ الاستعلام السابق ليس مثاليًا، فستُغيّر الحقل <code>id</code> إلى القيمة <code>4</code> لكل سجل يكون اسمه الأول مساويًا للقيمة <code>tecmint</code>. من الجيد استخدام مُطابقة أكثر من عمود واحد في عبارة <code>WHERE</code> لتقليل نسبة حدوث خطأ، كما في الاستعلام الآتي:
</p>

<pre class="ipsCode" id="ips_uid_657_49">
mysql&gt; UPDATE minttec SET id = 6 WHERE first_name = 'tecmint'AND last_name = '[dot]com'; 
Query OK, 1 row affected (0.03 sec)
Rows matched: 1  Changed: 1  Warnings: 0
mysql&gt;</pre>

<h2 id="حذف-أحد-أعمدة-الجدول">
	حذف أحد أعمدة الجدول
</h2>

<p>
	لنفترض أنَّك تحتاج إلى حذف أحد أعمدة الجدول غير الضرورية، ولنقل أنَّه العمود <code>country</code>:
</p>

<pre class="ipsCode" id="ips_uid_657_51">
mysql&gt; ALTER TABLE minttec drop country; 
Query OK, 3 rows affected (0.15 sec)
Records: 3  Duplicates: 0  Warnings: 0
mysql&gt;</pre>

<p>
	عرض بُنية الجدول:
</p>

<pre class="ipsCode" id="ips_uid_657_53">
mysql&gt; select * from minttec; 
+------+------------+-----------+-------------------+ 
| id   | first_name | last_name | email             | 
+------+------------+-----------+-------------------+ 
|    1 | Ravi       | Saive     | raivsaive@xyz.com | 
|    2 | Narad      | Shrestha  | narad@xyz.com     | 
|    6 | tecmint    | [dot]com  | tecmint@gmail.com | 
+------+------------+-----------+-------------------+
3 rows in set (0.00 sec) 
mysql&gt;</pre>

<h2 id="إعادة-تسمية-الجداول-في-mysql">
	إعادة تسمية الجداول في MySQL
</h2>

<p>
	ربما لا تجد اسم <code>minttec</code> ذا معنى، وتريد تحويله مثلًا إلى <code>tecmint_table</code> سنقوم بتغييره كالتّالي:
</p>

<pre class="ipsCode" id="ips_uid_657_55">
mysql&gt; RENAME TABLE minttec TO tecmint_table; 
Query OK, 0 rows affected (0.03 sec)
mysql&gt;</pre>

<h2 id="عرض-جميع-الجداول">
	عرض جميع الجداول
</h2>

<p>
	لرؤية جميع الجداول الموجودة في قاعدة البيانات الحالية:
</p>

<pre class="ipsCode" id="ips_uid_657_57">
mysql&gt; show tables; 
+-------------------+ 
| Tables_in_tecmint | 
+-------------------+ 
| tecmint_table     | 
+-------------------+
1 row in set (0.00 sec) 
mysql&gt;</pre>

<p>
	لاحظ إعادة تسمية الجدول.<br>
	لنأخذ الآن نسخةً احتياطيةً من قاعدة البيانات السابقة، وذلك عبر تنفيذ استعلامٍ من سطرٍ وحيد دون استخدام أيّة أدواتٍ معقدة. نفِّذ الشيفرة أدناه في سطر الأوامر وليس في مِحَث MySQL:
</p>

<pre class="ipsCode" id="ips_uid_657_59">
# mysqldump -u root -p tecmint &gt; tecmint.sql
check the dumped file on your desktop which would have contents something like
-- MySQL dump 10.13  Distrib 5.5.31, for debian-linux-gnu (i686) --
-- Server version 5.5.31-0+wheezy1 -- 
Dump completed on 2013-09-02 12:55:37</pre>

<p>
	من المستحسن الإبقاء على نسخ احتياطية لقواعد بياناتك، فاستعادة قاعدة بيانات MySQL هو أمرٌ بسيطٌ ويجرى بتنفيذ أمرٍ قصيرٍ في سطر الأوامر (أكرِّر، في سطر الأوامر وليس في مِحَث MySQL).<br>
	لكن ما رأيك أن نحذف قاعدة البيانات أولًا لنرى كيف ستتم عملية الاستعادة؟
</p>

<h2 id="حذف-قاعدة-بيانات">
	حذف قاعدة بيانات
</h2>

<pre class="ipsCode" id="ips_uid_657_61">
mysql&gt; drop database tecmint; 
Query OK, 1 row affected (0.02 sec)</pre>

<p>
	تحقق من وجود قاعدة بيانات باسم <code>tecmint</code> في خادوم قواعد البيانات عندك:
</p>

<pre class="ipsCode" id="ips_uid_657_63">
mysql&gt; show databases; 
+--------------------+ 
| Database           | 
+--------------------+ 
| information_schema | 
| my_database        | 
| mysql              | 
| performance_schema | 
| phpmyadmin         | 
| sisso              | 
| test               | 
+--------------------+
7 rows in set (0.00 sec) 
mysql&gt;</pre>

<p>
	رائع، لقد فقدنا قاعدة البيانات :-) لكن لا تقلق، فلقد أخذنا نسخةً احتياطيةً منها منذ قليل.
</p>

<h2 id="استعادة-قاعدة-بيانات-من-نسخة-احتياطية-منها">
	استعادة قاعدة بيانات من نسخةٍ احتياطيةٍ منها
</h2>

<p>
	نفِّذ الأمر الآتي لاستعادة قاعدة البيانات:
</p>

<pre class="ipsCode" id="ips_uid_657_65">
# mysql -u root -p tecmint &lt; tecmint.sql
Enter password:
ERROR 1049 (42000): Unknown database 'tecmint'</pre>

<p>
	ماذا حدث؟ لقد واجهنا رسالة خطأ، فنحن لم نُنشِئ قاعدة بيانات باسم <code>tecmint</code> بعد. لذا اذهب إلى مِحَث MySQL وأنشِئها:
</p>

<pre class="ipsCode" id="ips_uid_657_67">
mysql&gt; create database tecmint; 
Query OK, 1 row affected (0.00 sec) 
mysql&gt;</pre>

<p>
	حان الآن الوقت لتنفيذ أمر الاستعادة في سطر الأوامر:
</p>

<pre class="ipsCode" id="ips_uid_657_69">
# mysql -u root -p tecmint &lt; tecmint.sql 
Enter password:</pre>

<p>
	لم تظهر بوجهنا أيّة رسائل خطأ مرعبة، لنتحقق الآن من وجود القاعدة في خادومنا:
</p>

<pre class="ipsCode" id="ips_uid_657_71">
mysql&gt; show databases; 
+--------------------+ 
| Database           | 
+--------------------+ 
| information_schema | 
| mysql              | 
| performance_schema | 
| tecmint            | 
| test               | 
+--------------------+ 
8 rows in set (0.00 sec)</pre>

<p>
	ثم سنتحقق من محتويات قاعدة البيانات (أي جداولها):
</p>

<pre class="ipsCode" id="ips_uid_657_73">
mysql&gt; show tables from tecmint;
+-------------------+ 
| Tables_in_tecmint | 
+-------------------+ 
| tecmint_table     | 
+-------------------+ 
1 row in set (0.00 sec)
mysql&gt;</pre>

<p>
	وليطمئن قلبنا، سنرى محتويات الجدول:
</p>

<pre class="ipsCode" id="ips_uid_657_75">
mysql&gt; select * from tecmint_table; 
+------+------------+-----------+-------------------+ 
| id   | first_name | last_name | email             | 
+------+------------+-----------+-------------------+ 
|    1 | Ravi       | Saive     | raivsaive@xyz.com | 
|    2 | Narad      | Shrestha  | narad@xyz.com     | 
|    6 | tecmint    | [dot]com  | tecmint@gmail.com | 
+------+------------+-----------+-------------------+
3 rows in set (0.00 sec)</pre>

<p>
	هذه ليست نهاية المطاف، ما زال أمامنا مناقشة بعض المفاهيم مثل primary key، و foreign key…<br>
	ترجمة -وبتصرّف- للمقال <a href="http://www.tecmint.com/gliding-through-database-mysql-in-a-nutshell-part-i/" rel="external nofollow">MySQL Basic Database Administration Commands – Part I</a>.
</p>
]]></description><guid isPermaLink="false">295</guid><pubDate>Sun, 13 Nov 2016 09:59:00 +0000</pubDate></item><item><title>&#x643;&#x64A;&#x641;&#x64A;&#x629; &#x625;&#x646;&#x634;&#x627;&#x621; &#x627;&#x644;&#x646;&#x633;&#x62E; &#x627;&#x644;&#x627;&#x62D;&#x62A;&#x64A;&#x627;&#x637;&#x64A;&#x629; &#x627;&#x644;&#x633;&#x627;&#x62E;&#x646;&#x629; &#x644;&#x642;&#x648;&#x627;&#x639;&#x62F; &#x628;&#x64A;&#x627;&#x646;&#x627;&#x62A; MySQL &#x628;&#x627;&#x633;&#x62A;&#x62E;&#x62F;&#x627;&#x645; Percona XtraBackup &#x639;&#x644;&#x649; Ubuntu</title><link>https://academy.hsoub.com/devops/servers/databases/mysql/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D8%A7%D9%84%D9%86%D8%B3%D8%AE-%D8%A7%D9%84%D8%A7%D8%AD%D8%AA%D9%8A%D8%A7%D8%B7%D9%8A%D8%A9-%D8%A7%D9%84%D8%B3%D8%A7%D8%AE%D9%86%D8%A9-%D9%84%D9%82%D9%88%D8%A7%D8%B9%D8%AF-%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-mysql-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-percona-xtrabackup-%D8%B9%D9%84%D9%89-ubuntu-r159/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2015_12/hot-backup-mysql_(1).png.6dcaf0b10f1951bc0d8fe6bcc9b67266.png" /></p>

<div id="wmd-preview-section-6"><p id="كيفية-إنشاء-النسخ-الاحتياطية-الساخنة-لقواعد-بيانات-mysql-باستخدام-percona-xtrabackup-على-ubuntu">من التحديات الشائعة التي نصادفها عند التعامل مع أنظمة قواعد البيانات النشطة active هو القيام بنسخ احتياطيّة ساخنة hot backups، وهو إنشاء نسخ احتياطيّة بدون إيقاف خدمة قاعدة البيانات أو جعلها قابلة للقراءة فقط، ينتج عادة عن نسخ ملفّات قاعدة البيانات النشطة ببساطة نسخة من قاعدة البيانات غير مستقرّة داخليًّا، أي تكون غير قابلة للاستخدام أو فاقدة لبعض المعاملات transactions التي حدثت خلال هذا النسخ، من ناحية أخرى فإنّ إيقاف قاعدة البيانات من أجل النسخ الاحتياطي المُجدوَل يجعل الأجزاء المعتمدة على قاعدة البيانات من تطبيقنا غير متوفّرة. <strong>Percona XtraBackup</strong> هو أداة مفتوحة المصدر تُستَخدم للالتفاف على هذه المشكلة وإنشاء نُسَخ احتياطيّة كاملة full backups أو تزايديّة incremental backups لقواعد بيانات قيد التشغيل من نوع MySQL، MariaDB، و Percona Server، وهي معروفة أيضًا باسم النُسَخ الاحتياطيّة الساخنة hot backups.</p><p style="text-align: center;"><a href="https://academy.hsoub.com/uploads/monthly_2015_12/hot-backup-mysql_(1).png.0207ad4fe5a8ecb79eb57d98ec9e86a2.png" class="ipsAttachLink ipsAttachLink_image"><img data-fileid="9678" src="https://academy.hsoub.com/uploads/monthly_2015_12/hot-backup-mysql_(1).thumb.png.5771cc5c1722981f3cd4d3249cf39151.png" class="ipsImage ipsImage_thumbnailed" alt="hot-backup-mysql_(1).thumb.png.5771cc5c1"></a></p></div><div id="wmd-preview-section-7"><p>وعلى النقيض من النُّسَخ الاحتياطيّة المنطقيّة logical backups التي تنتجها أدوات مثل mysqldump، تقوم أداة <strong>XtraBackup</strong> بإنشاء نُسَخ احتياطيّة ملموسة physical backups لملفّات قواعد البيانات، أي تقوم بعمل نسخة لملفّات البيانات، وتطبّق بعدها سجل المعاملات (transaction log (a.k.a. redo log على النُّسخ الاحتياطيّة الملموسة لتُعيد ملء أي مُعاملات نشطة لم تكتمل خلال إنشاء النُّسَخ الاحتياطيّة، مما يُؤدّي إلى نُسَخ احتياطيّة مستقرّة لقاعدة بيانات قيد التشغيل، يُمكِن بعدها النسخ الاحتياطي لنسخة قاعدة البيانات الاحتياطيّة إلى موقع بعيد remote location باستخدام <a href="https://academy.hsoub.com/devops/linux/%D9%83%D9%8A%D9%81-%D8%AA%D8%B3%D8%AA%D8%AE%D8%AF%D9%90%D9%85-rsync-%D9%84%D9%85%D8%B2%D8%A7%D9%85%D9%86%D8%A9-%D9%85%D8%AC%D9%84%D9%91%D8%AF%D8%A7%D8%AA-%D8%A8%D9%8A%D9%86-%D8%A7%D9%84%D8%AC%D9%87%D8%A7%D8%B2-%D8%A7%D9%84%D9%85%D8%AD%D9%84%D9%91%D9%8A-%D9%88%D8%A7%D9%84%D8%AE%D8%A7%D8%AF%D9%88%D9%85-r50/">rsync</a> أو نظام نسخ احتياطي مثل <a href="https://academy.hsoub.com/devops/servers/%D9%83%D9%8A%D9%81-%D8%AA%D8%AB%D8%A8%D8%AA-%D8%AE%D8%A7%D8%AF%D9%88%D9%85-bacula-%D9%84%D9%84%D9%86%D8%B3%D8%AE-%D8%A7%D9%84%D8%A7%D8%AD%D8%AA%D9%8A%D8%A7%D8%B7%D9%8A-%D8%B9%D9%84%D9%89-ubuntu-1404-r144/">Bacula</a>.</p><p>سنتعلّم في هذا الدّرس كيفيّة القيام بنسخة احتياطيّة كاملة وساخنة لقواعد بيانات <strong>MySQL</strong> أو <strong>MariaDB</strong> باستخدام <strong>Percona XtraBackup</strong> على Ubuntu، تمّت أيضًا تغطية عمليّة استعادة قاعدة البيانات من نسخة احتياطيّة.</p></div><div id="wmd-preview-section-8"><h2 id="المتطلبات-الأساسية">المتطلبات الأساسية</h2><p>يجب أن تمتلك ما يلي من أجل متابعة هذا الدّرس:</p><ul><li>صلاحيّات مستخدم جذر Superuser على نظام Ubuntu</li><li>قاعدة بيانات MySQL أو MariaDB قيد التشغيل</li><li>النفاذ إلى المستخدم المُدير (admin (root لقاعدة بياناتك</li></ul><p>ومن أجل القيام بنسخة احتياطيّة ساخنة لقاعدة بياناتك يجب أيضًا أن تستخدم مُحرِّك التخزين InnoDB لأنّ XtraBackup تعتمد على سجل معاملات يُحافِظ عليه InnoDB، إن كانت قواعد بياناتك تستخدم مُحرِّك التخزين MyISAM فلا يزال بإمكانك استخدام XtraBackup ولكن سيتم قفل قاعدة البيانات لفترة قصيرة من الوقت في أواخر عمليّة النسخ الاحتياطي.</p></div><div id="wmd-preview-section-9"><h3 id="1-التحقق-من-محرك-التخزين">1- التحقق من محرك التخزين</h3><p>إن لم تكن متأكدًا من مُحرِّك التخزين الذي تستخدمه قاعدة بياناتك فتستطيع معرفته بعدّة طرق، إحدى الطرق هي استخدام وحدة التحكّم console في MySQL لاختيار قاعدة البيانات المطلوبة ومن ثمّ الحصول على حالة كل جدول فيها.</p><p>ندخل في البداية إلى وحدة التحكّم console في MySQL:</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">mysql -u root -p</pre><p>نقوم بإدخال كلمة سر المستخدم الجذري root في MySQL.</p><p>وفي مُحث MySQL prompt نختار قاعدة البيانات التي نريد التحقّق منها، تأكد من أن تضع اسم قاعدة بياناتك هنا بدلًا من<span style="font-family:courier new,courier,monospace;"> database_name</span>:</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">mysql&gt; USE database_name;</pre><p>نطبع بعدها حالات جدولها:</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">mysql&gt; SHOW TABLE STATUS\G;</pre><p>ينبغي الإشارة للمحرك لكل صف من قاعدة البيانات:</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">... 
*************************** 11. row *************************** 
Name: wp_users 
Engine: InnoDB 
...</pre><p>نغادر وحدة التحكّم console حالما ننتهي من هذا.</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">mysql&gt; exit</pre><p>فلنقم بتثبيت Percona XtraBackup.</p></div><div id="wmd-preview-section-10"><h2 id="تثبيت-percona-xtrabackup">تثبيت Percona XtraBackup</h2><p>أسهل طريقة لتثبيت <strong>Percona XtraBackup</strong> هي استخدام <span style="font-family:courier new,courier,monospace;">apt-get</span>.</p><p>نضيف مفتاح مستودع Percona باستخدام هذا الأمر:</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">sudo apt-key adv --keyserver keys.gnupg.net --recv-keys 1C4CBDCDCD2EFD2A</pre><p>نضيف بعدها مستودع Percona إلى مصادر apt لدينا:</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">sudo sh -c "echo 'deb http://repo.percona.com/apt trusty main' &gt; /etc/apt/sources.list.d/percona.list" sudo sh -c "echo 'deb-src http://repo.percona.com/apt trusty main' &gt;&gt; /etc/apt/sources.list.d/percona.list"</pre><p>نقوم بتنفيذ الأمر التالي لتحديث مصادر <span style="font-family:courier new,courier,monospace;">apt</span>:</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">sudo apt-get update</pre><p>نستطيع أخيرًا تنفيذ الأمر التالي لتثبيت XtraBackup:</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">sudo apt-get install percona-xtrabackup</pre><p>تتألف XtraBackup بشكل أساسي من برنامج XtraBackup و script مكتوب بلغة Perl يُدعى <strong>innobackupex</strong> سنستخدمه لإنشاء نُسَخ احتياطيّة لقواعد بياناتنا.</p></div><div id="wmd-preview-section-11"><h2 id="التحضيرات-لأول-مرة">التحضيرات لأول مرة</h2><p>نحتاج قبل استخدام XtraBackup لأوّل مرّة إلى تحضير النظام ومستخدم MySQL الذي سيستخدمه XtraBackup، يُغطّي هذا القسم التحضيرات الأوليّة.</p></div><div id="wmd-preview-section-12"><h3 id="1-مستخدم-النظام">1- مستخدم النظام</h3><p>إذا لم نكن نخطّط لاستخدام المستخدم الجذري root للنظام فيجب علينا القيام ببعض التحضيرات الأساسيّة للتأكد من أنّه يُمكن تنفيذ XtraBackup بشكل صحيح، سنفترض أنّك قمت بتسجيل الدخول باستخدام المستخدم الذي سيشغّل XtraBackup وأنّه يمتلك صلاحيّات مستخدم جذر superuser.</p><p>نضيف مستخدم النظام إلى المجموعة "mysql" (ضع اسم المستخدم لديك بدلًا من username):</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">sudo gpasswd -a username mysql</pre><p>نقوم بإنشاء الدليل الذي سنستخدمه لتخزين النُّسَخ الاحتياطيّة التي يقوم XtraBackup بعملها:</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">sudo mkdir -p /data/backups sudo chown -R username: /data</pre><p>يتأكّد الأمر <span style="font-family:courier new,courier,monospace;">chown</span> من قدرة المستخدم على الكتابة إلى دليل النُّسَخ الاحتياطيّة.</p></div><div id="wmd-preview-section-13"><h3 id="2-مستخدم-mysql">2- مستخدم MySQL</h3><p>يحتاج XtraBackup إلى مستخدم MySQL لكي يستخدمه لإنشاء النُّسَخ الاحتياطيّة، فلنقم بإنشاء واحد الآن. <br>ندخل إلى وحدة التحكّم console في MySQL بهذا الأمر:</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">mysql -u root -p</pre><p>نقوم بإدخال كلمة سر المستخدم الجذري root في MySQL.</p><p>نُنشِئ في مُحِث MySQL prompt مستخدم MySQL جديد ونعيّن كلمة سر له، يُدعى المستخدم في هذا المثال "bkpuser" وكلمة السّر هي "bkppassword"، قم بتغييرهما إلى شيء أكثر أمانًا:</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">mysql&gt; CREATE USER 'bkpuser'@'localhost' IDENTIFIED BY 'bkppassword'</pre><p>نقوم بعدها بمنح grant مستخدم MySQL الجديد صلاحيّات إعادة التحميل reload، القفل lock، والتكرار replication لكافّة قواعد البيانات:</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">mysql&gt; GRANT RELOAD, LOCK TABLES, REPLICATION CLIENT ON *.* TO 'bkpuser'@'localhost';
FLUSH PRIVILEGES; </pre><p>وهي الحد الأدنى من الصلاحيّات التي يحتاجها XtraBackup لإنشاء نُسَخ احتياطيّة كاملة لقواعد البيانات.</p><p>عند الانتهاء نقوم بالخروج من لوحة تحكّم MySQL console:</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">mysql&gt; exit</pre><p>نحن الآن جاهزون لإنشاء نسخة احتياطيّة كاملة لقواعد بياناتنا.</p></div><div id="wmd-preview-section-14"><h2 id="القيام-بنسخة-احتياطية-ساخنة-كاملة">القيام بنسخة احتياطية ساخنة كاملة</h2><p>يُغطّي هذا القسم الخطوات الضرورية لإنشاء نسخة احتياطيّة ساخنة كاملة لقاعدة بيانات MySQL باستخدام XtraBackup، بعد التأكّد من أنّ أذونات permissions ملفّات قاعدة البيانات صحيحة سنستخدم XtraBackup لإنشاء create النسخة الاحتياطيّة وتحضيرها prepare.</p></div><div id="wmd-preview-section-15"><h3 id="1-تحديث-أذونات-datadir">1- تحديث أذونات Datadir</h3><p>يتم تخزين ملفّات قاعدة بيانات MySQL على Ubuntu في المسار <span style="font-family:courier new,courier,monospace;">var/lib/mysql/</span>، وهو الذي يتم الإشارة إليه أحيانًا بـ datadir، يتم تقييد النفاذ إلى datadir افتراضيًّا فقط للمستخدم <span style="font-family:courier new,courier,monospace;">mysql</span>، يتطلّب XtraBackup نفاذًا إلى هذا الدّليل لإنشاء نسخه الاحتياطيّة، لذا نقوم بتنفيذ بعض الأوامر للتأكّد من امتلاك مستخدم النظام الذي أعددناه سابقًا-كعضو في المجموعة mysql- للأذونات المناسبة:</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">sudo chown -R mysql: /var/lib/mysql 
sudo find /var/lib/mysql -type d -exec chmod 770 "{}" \;</pre><p>تضمن هذه الأوامر أنّ كافّة الأدّلة في datadir قابلة للنفاذ من قبل المجموعة mysql، ويجب تنفيذها قبل كل نسخة احتياطيّة.</p><h3>2- إنشاء نسخة احتياطية</h3></div><div id="wmd-preview-section-16"><p>نحن الآن على استعداد لإنشاء النسخة الاحتياطيّة، نستخدم الأداة <strong>innobackupex</strong> أثناء تشغيل قاعدة بيانات MySQL لفعل هذا، قم بتنفيذ هذا الأمر بعد وضع اسم مستخدمك وكلمة سرك لتتوافق مع معلومات تسجيل دخول مستخدم MySQL لديك:</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">innobackupex --user=bkpuser --password=bkppassword --no-timestamp /data/backups/new_backup</pre><p>سيقوم هذا بإنشاء نسخة احتياطيّة لقاعدة البيانات في الموقع المُحدّد <span style="font-family:courier new,courier,monospace;">data/backups/new_backup/</span>:</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">innobackupex output innobackupex: Backup created in directory '/data/backups/new_backup' 
150420 13:50:10 innobackupex: Connection to database server closed 
150420 13:50:10 innobackupex: completed OK!</pre><p>وبشكل بديل تستطيع إزالة <span style="font-family:courier new,courier,monospace;">no-timestamp--</span> لكي يقوم XtraBackup بإنشاء دليل النسخة الاحتياطيّة بناءً على الختم الزمني timestamp الحالي كما يلي:</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">innobackupex --user=bkpuser --password=bkppassword /data/backups</pre><p>سيقوم هذا بإنشاء نسخة احتياطيّة لقاعدة البيانات في دليل فرعي مُولَّد تلقائيًّا كما يلي:</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">innobackupex output — no timestamp innobackupex: Backup created in directory '/data/backups/2015-04-20_13-50-07' 
150420 13:50:10 innobackupex: Connection to database server closed 
150420 13:50:10 innobackupex: completed OK!</pre><p>ستعيد أي طريقة نستخدمها العبارة "innobackupex: completed OK" في السّطر الأخير من الخَرْج، ينتج عن النّسخة الاحتياطيّة الناجحة نسخة من قاعدة البيانات في المسار <span style="font-family:courier new,courier,monospace;">datadir</span> والتي يجب تحضيرها قبل استخدامها.</p></div><div id="wmd-preview-section-17"><h2 id="تحضير-النسخة-الاحتياطية">تحضير النسخة الاحتياطية</h2><p>الخطوة الأخيرة في إنشاء نسخة احتياطيّة ساخنة باستخدام XtraBackup هي تحضيرها، ويتضمّن هذا إعادة "replaying" سجل المعاملات لتطبيق أي معاملة غير مرتبطة بالنسخة الاحتياطيّة، يجعل التحضير بيانات النسخة الاحتياطيّة مستقرة وقابلة للاستخدام من أجل الاستعادة.</p><p>سنحضّر بحسب مثالنا النسخة الاحتياطيّة التي أنشأناها في المسار <span style="font-family:courier new,courier,monospace;">data/backups/new_backup/</span>، ضع المسار الفعلي للنسخة الاحتياطيّة لديك:</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">innobackupex --apply-log /data/backups/new_backup</pre><p>يجب أن نرى مرّة أخرى العبارة "innobackupex: completed OK" في السطر الأخير من الخَرْج.</p><p>تمّ إنشاء النسخة الاحتياطيّة لقاعدة البيانات وهي جاهزة لاستعادتها إلى قاعدة بياناتنا، إن كنت تملك نظام نسخ احتياطي للملفّات مثل <a href="https://academy.hsoub.com/devops/servers/%D9%83%D9%8A%D9%81-%D8%AA%D8%AB%D8%A8%D8%AA-%D8%AE%D8%A7%D8%AF%D9%88%D9%85-bacula-%D9%84%D9%84%D9%86%D8%B3%D8%AE-%D8%A7%D9%84%D8%A7%D8%AD%D8%AA%D9%8A%D8%A7%D8%B7%D9%8A-%D8%B9%D9%84%D9%89-ubuntu-1404-r144/">Bacula</a> فيجب تضمين هذه النسخة الاحتياطيّة لقاعدة البيانات كجزء من اختيار النسخة الاحتياطيّة.</p><p>يُغطّي القسم التالي كيفيّة استعادة قاعدة البيانات من النسخة الاحتياطيّة التي أنشأناها للتو.</p></div><div id="wmd-preview-section-18"><h2 id="القيام-باستعادة-النسخة-الاحتياطية">القيام باستعادة النسخة الاحتياطية</h2><p>تتطلّب استعادة قاعدة البيانات باستخدام XtraBackup إيقاف قاعدة البيانات وأن يكون المسار <span style="font-family:courier new,courier,monospace;">datadir</span> فارغًا.</p><p>نوقف خدمة MySQL باستخدام هذا الأمر:</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">sudo service mysql stop</pre><p>ننقل أو نحذف محتويات <span style="font-family:courier new,courier,monospace;">datadir</span> (وهو المسار <span style="font-family:courier new,courier,monospace;">var/lib/mysql/</span>)، في حالتنا سننقله ببساطة إلى مكان مؤقّت:</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">mkdir /tmp/mysql mv /var/lib/mysql/* /tmp/mysql/</pre><p>نستطيع الآن استعادة قاعدة البيانات من نسختنا الاحتياطيّة "<span style="font-family:courier new,courier,monospace;">new_backup</span>":</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">innobackupex --copy-back /data/backups/new_backup</pre><p>إن تم الأمر بنجاح فينبغي أن يكون السطر الأخير من الخَرْج هو العبارة "innobackupex: completed OK".</p><p>تنتمي الملفّات التي تمّت استعادتها غالبًا إلى المستخدم الذي قام بتنفيذ عمليّة الاستعادة، نُعيد الملكيّة إلى mysql لكي تستطيع MySQL قراءة وكتابة الملفّات:</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">sudo chown -R mysql: /var/lib/mysql</pre><p>أصبحنا مستعدين لبدء MySQL:</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">sudo service mysql start</pre><p>هذا هو كل شيء، يجب أن تكون قاعدة بيانات MySQL التي استعدناها قيد التشغيل الآن.</p></div><div id="wmd-preview-section-19"><h2 id="الخاتمة">الخاتمة</h2><p>بعد أن أصبحت الآن قادرًا على إنشاء نُسَخ احتياطيّة ساخنة لقاعدة بيانات MySQL باستخدام<strong> Percona XtraBackup</strong> فهنالك العديد من الأشياء التي يجب أن تنظر إلى إعدادها.</p><p>يُنصَح أولًا بأتمتة العمليّة بحيث يتم إنشاء النُّسَخ الاحتياطيّة وفق جدول، يجب عليك ثانيًا القيام بنسخ بعيد remote للنسخ الاحتياطيّة في حال حدثت مشاكل في خادوم قاعدة البيانات باستخدام أدوات مثل <a href="https://academy.hsoub.com/devops/linux/%D9%83%D9%8A%D9%81-%D8%AA%D8%B3%D8%AA%D8%AE%D8%AF%D9%90%D9%85-rsync-%D9%84%D9%85%D8%B2%D8%A7%D9%85%D9%86%D8%A9-%D9%85%D8%AC%D9%84%D9%91%D8%AF%D8%A7%D8%AA-%D8%A8%D9%8A%D9%86-%D8%A7%D9%84%D8%AC%D9%87%D8%A7%D8%B2-%D8%A7%D9%84%D9%85%D8%AD%D9%84%D9%91%D9%8A-%D9%88%D8%A7%D9%84%D8%AE%D8%A7%D8%AF%D9%88%D9%85-r50/">rsync</a> أو نظام نُسَخ احتياطيّة للملفّات على الشبكة مثل <a href="https://academy.hsoub.com/devops/servers/%D9%83%D9%8A%D9%81-%D8%AA%D8%AB%D8%A8%D8%AA-%D8%AE%D8%A7%D8%AF%D9%88%D9%85-bacula-%D9%84%D9%84%D9%86%D8%B3%D8%AE-%D8%A7%D9%84%D8%A7%D8%AD%D8%AA%D9%8A%D8%A7%D8%B7%D9%8A-%D8%B9%D9%84%D9%89-ubuntu-1404-r144/">Bacula</a>، سترغب بعدها في النظر في مداورة rotating النسخ الاحتياطيّة لديك (أي حذف النسخ الاحتياطيّة القديمة على أساس مُجدوَل) وإنشاء نُسَخ احتياطيّة تزايديّة (باستخدام XtraBackup) لتوفير مساحة القرص.</p><p>ترجمة -وبتصرّف- لـ <a rel="external nofollow" href="https://www.digitalocean.com/community/tutorials/how-to-create-hot-backups-of-mysql-databases-with-percona-xtrabackup-on-ubuntu-14-04">How To Create Hot Backups of MySQL Databases with Percona XtraBackup on Ubuntu 14.04</a> لصاحبه Mitchell Anicas.</p></div>
]]></description><guid isPermaLink="false">159</guid><pubDate>Fri, 18 Dec 2015 22:34:00 +0000</pubDate></item></channel></rss>
