مقاله

تفاوت MySQL و MariaDB برای توسعه‌دهنده Laravel — کدام را انتخاب کنیم؟

تفاوت MySQL و MariaDB برای توسعه‌دهنده Laravel — کدام را انتخاب کنیم؟

مقایسه MySQL 8 و MariaDB 10.11 برای Laravel: سازگاری، performance، licensing، migration و تنظیمات .env — با توصیه عملی برای ایران.

MySQL و MariaDB هر دو با Laravel و از طریق همان extension یعنی pdo_mysql کار می‌کنند و Eloquent روی هر دو یکسان نوشته می‌شود. اما از Laravel 11 به بعد، MariaDB درایور جدای mariadb هم دارد، و تفاوت نسخه‌ها در JSON، collation، قفل‌گذاری و ابزارهای dump می‌تواند روی migration، انتقال داده و نگهداری اثر بگذارد. در XAMPP معمولاً MariaDB نصب است؛ روی VPS یا سرویس managed ممکن است MySQL 8 باشد. این مقاله کمک می‌کند بدون تعصب انتخاب کنید.

خلاصه: برای بیشتر پروژه‌های Laravel هر دو کار می‌کنند، اما «قابل تعویض کامل» نیستند. تصمیم را بر اساس نسخهٔ دقیقی که در production دارید بگیرید، نه نام محصول: Laravel 12 طبق مستندات رسمی MariaDB 10.3+ و MySQL 5.7+ را پشتیبانی می‌کند، ولی بسیاری از قابلیت‌ها به نسخه وابسته‌اند. local، CI و production را روی یک محصول و نسخهٔ یکسان نگه دارید و قبل از جابه‌جایی بین این دو، روی staging تست کنید.

رابطه تاریخی — چرا دو تا داریم؟

MariaDB فورک community-driven از MySQL است که پس از خرید Sun (مالک MySQL) توسط Oracle شکل گرفت. سال‌ها تقریباً جایگزین مستقیم هم بودند؛ اما از MySQL 8 و نسل‌های جدید MariaDB، مسیر دو محصول جداتر شده: پیاده‌سازی JSON، collationهای پیش‌فرض، replication و بخشی از optimizer متفاوت‌اند. برای CRUD معمولی Laravel این تفاوت‌ها اغلب دیده نمی‌شوند؛ در migration، انتقال داده و queryهای خاص دیده می‌شوند.

سازگاری با Laravel

Laravel رسماً هر دو را پشتیبانی می‌کند. در config/database.php دو اتصال جدا وجود دارد: mysql و mariadb:

# MySQL
DB_CONNECTION=mysql

# MariaDB
DB_CONNECTION=mariadb
DB_HOST=127.0.0.1
DB_PORT=3306

درایور mariadb همان اتصال MySQL را گسترش می‌دهد اما grammar مخصوص MariaDB را به کار می‌برد. چند نمونه از کد Laravel 12:

  • ستون uuid() در migration روی MariaDB 10.7 به بالا نوع بومی uuid می‌سازد و در نسخه‌های قدیمی‌تر char(36).
  • renameColumn روی MariaDB قدیمی‌تر از 10.5.2 با syntax قدیمی اجرا می‌شود.
  • شرط‌های JSON مثل where('options->lang', 'fa') روی MariaDB به json_value() و روی MySQL به json_unquote(json_extract()) ترجمه می‌شوند.
  • php artisan schema:dump روی MariaDB از mariadb-dump استفاده می‌کند.

اتصال mysql روی سرور MariaDB هم در عمل برای بیشتر کارها جواب می‌دهد و در پروژه‌های قدیمی رایج است، اما با درایور mariadb این تفاوت‌ها را Laravel خودش مدیریت می‌کند. از utf8mb4 با collationی مثل utf8mb4_unicode_ci برای فارسی استفاده کنید. برای دیدن نسخه و نوع سرور: php artisan db:show یا SELECT VERSION(); — در MariaDB رشتهٔ نسخه شامل کلمهٔ MariaDB است.

نسخه‌ها مهم‌تر از نام محصول

«MySQL» و «MariaDB» هرکدام چند خط انتشار دارند. MySQL از 8.4 مدل LTS در کنار نسخه‌های Innovation دارد و MySQL 5.7 در اکتبر ۲۰۲۳ به پایان پشتیبانی رسیده است. MariaDB هم نسخه‌های LTS (مثل 10.11 و 11.4) و نسخه‌های کوتاه‌مدت دارد. قبل از هر مقایسه، نسخهٔ دقیق production را مشخص کنید و تاریخ پایان پشتیبانی آن را در صفحهٔ رسمی lifecycle همان محصول ببینید. قابلیتی که در یک نسخه هست ممکن است در نسخهٔ نصب‌شده روی هاست شما نباشد.

مقایسه فنی خلاصه

معیارMySQLMariaDB
لایسنسCommunity با GPLv2 + نسخه‌های تجاری OracleMariaDB Server با GPLv2
درایور Laravelmysqlmariadb (از Laravel 11)
JSONنوع JSON بومی با ذخیره‌سازی باینریJSON نام مستعار LONGTEXT با بررسی اعتبار JSON
UUID بومینوع جدا ندارد (Laravel: char(36))نوع uuid از 10.7
collation پیش‌فرضدر MySQL 8: utf8mb4_0900_ai_ciمتفاوت و وابسته به نسخه
SKIP LOCKEDاز 8.0.1از 10.6
Window functions و CTEاز 8.0از 10.2
Replication و clusterGroup Replication / InnoDB ClusterGalera Cluster؛ پیاده‌سازی GTID با MySQL متفاوت است
Performanceوابسته به نسخه، تنظیمات، schema و workload — benchmark با دادهٔ خودتان

کی MySQL؟

  • هاست یا تیم ops فقط MySQL ارائه یا پشتیبانی می‌کند
  • نیاز به ویژگی یا ابزار خاص Oracle MySQL، یا قرارداد پشتیبانی تجاری آن
  • managed service که موتور MySQL را با نسخهٔ مشخص ارائه می‌دهد
  • داده و ابزارهای موجود (مثلاً collation 0900 یا replication فعلی) بر پایهٔ MySQL است

کی MariaDB؟

  • XAMPP/local پیش‌فرض و هاستی که MariaDB نصب دارد
  • هاست ایرانی با MariaDB رایج
  • ترجیح open-source خالص بدون نسخهٔ تجاری Oracle
  • برخی توزیع‌های لینوکس MariaDB را به‌عنوان بستهٔ پیش‌فرض ارائه می‌کنند
  • نیاز به Galera Cluster یا قابلیت‌های خاص MariaDB

تفاوت‌هایی که Laravel dev باید بداند

JSON

متد json() در migration روی هر دو کار می‌کند و castهای Eloquent یکسان‌اند. تفاوت در لایهٔ دیتابیس است: MySQL ستون JSON را در قالب باینری مخصوص ذخیره می‌کند، اما در MariaDB نوع JSON نام دیگر LONGTEXT است که اعتبارش با constraint بررسی می‌شود. در queryهای ساده تفاوتی حس نمی‌کنید؛ در index روی مقادیر JSON، توابع کمتر رایج JSON و انتقال dump بین دو محصول، مستندات نسخهٔ خودتان را چک کنید.

collation و charset

اگر دیتابیس روی MySQL 8 با collation پیش‌فرض utf8mb4_0900_ai_ci ساخته شده باشد، restore کردن dump آن روی نسخه‌ای از MariaDB که این collation را نمی‌شناسد با خطای «Unknown collation» متوقف می‌شود. Laravel برای جدول‌هایی که خودش می‌سازد از مقدار DB_COLLATION (پیش‌فرض utf8mb4_unicode_ci) استفاده می‌کند، اما collation پیش‌فرض خود دیتابیس و جدول‌هایی که دستی ساخته شده‌اند ممکن است متفاوت باشند. قبل از انتقال، collation جدول‌ها و ستون‌ها را بررسی کنید.

fulltext و index

در جستجوی fulltext فارسی هر دو محدودیت دارند — اغلب Elasticsearch یا Meilisearch جدا می‌آوریم. indexهای معمولی B-tree، index ترکیبی و unique در هر دو یکسان در migration تعریف می‌شوند.

تفاوت در EXPLAIN

optimizer دو محصول یکسان نیست و خروجی EXPLAIN ممکن است برای یک query متفاوت باشد. برای بهینه‌سازی کوئری روی همان engine و نسخه‌ای تست کنید که production است.

تراکنش و قفل‌گذاری

هر دو به‌طور پیش‌فرض از InnoDB با سطح ایزولاسیون REPEATABLE READ استفاده می‌کنند و DB::transaction()، lockForUpdate() و sharedLock() روی هر دو کار می‌کنند. تفاوت در جزئیات نسخه است: مثلاً driver صف database در Laravel فقط روی MySQL 8.0.1+ و MariaDB 10.6+ از FOR UPDATE SKIP LOCKED استفاده می‌کند تا workerها روی یک job منتظر هم نمانند. deadlock و retry در تراکنش‌های دیتابیس در Laravel بررسی شده.

migration از یکی به دیگری

جابه‌جایی بین MySQL و MariaDB معمولاً با dump و restore انجام می‌شود، اما بین نسخه‌های جدید همیشه ساده نیست — به‌خصوص از MySQL 8 به MariaDB. مراحل محتاطانه:

  1. نسخهٔ دقیق مبدأ و مقصد را مشخص کنید و از دیتابیس فعلی backup کامل و قابل restore بگیرید — راهنمای بکاپ سایت.
  2. dump را با ابزار مبدأ بگیرید (mysqldump در MySQL یا mariadb-dump در MariaDB؛ در بسیاری از نسخه‌های MariaDB نام mysqldump هم برای سازگاری هست) و برای InnoDB از --single-transaction استفاده کنید؛ اگر routine و trigger دارید --routines و --triggers را اضافه کنید.
  3. collationهای 0900، ستون‌های JSON و syntax خاص هر محصول را در dump بررسی کنید.
  4. روی staging با همان نسخهٔ مقصد restore کنید، DB_CONNECTION را به درایور درست تغییر دهید و php artisan migrate:status و تست‌های پروژه را اجرا کنید.
  5. بعد از تأیید، در زمان کم‌ترافیک انتقال دهید و مسیر بازگشت را آماده نگه دارید.

تنظیم Laravel برای production

DB_CONNECTION=mariadb   # یا mysql، مطابق سرور واقعی
DB_CHARSET=utf8mb4
DB_COLLATION=utf8mb4_unicode_ci

در مقیاس بالا، ابزارهای proxy و connection pooling مثل ProxySQL با هر دو کار می‌کنند؛ برای بیشتر سایت‌ها لازم نیست. پیش از انتخاب هاست یا سرویس managed، نسخهٔ موجود، سیاست به‌روزرسانی، امکان backup و restore و دسترسی به لاگ کندی query را بپرسید.

توسعه local و production

رایج‌ترین مشکل، تفاوت محیط‌هاست: local روی MariaDB در XAMPP، production روی MySQL 8 (یا برعکس) و تست‌ها روی SQLite. SQLite برای تست سریع مفید است، اما رفتار JSON، collation و قفل‌گذاری را مثل MySQL/MariaDB شبیه‌سازی نمی‌کند. دست‌کم یک مرحله در CI یا staging داشته باشید که migrationها و تست‌های مهم را روی همان محصول و نسخهٔ production اجرا کند؛ Docker با image نسخهٔ مشخص این کار را ساده می‌کند — Docker Compose برای Laravel.

Redis جدا از بحث SQL

کش و صف — REDIS_HOST — مکمل دیتابیس است نه جایگزین؛ انتخاب MySQL یا MariaDB روی آن اثری ندارد.

چک‌لیست انتخاب

  • هاست یا سرویس production کدام محصول و چه نسخه‌ای را ارائه می‌دهد؟ پایان پشتیبانی آن نسخه کی است؟
  • داده یا اپلیکیشن موجود به قابلیت خاصی (JSON سنگین، collation خاص، replication فعلی) وابسته است؟
  • local، CI و production روی یک محصول و نسخهٔ یکسان‌اند؟
  • DB_CONNECTION با نوع واقعی سرور (mysql یا mariadb) هماهنگ است؟
  • تیم ops با ابزارهای backup، مانیتورینگ و ارتقای کدام محصول آشناتر است؟
  • مسیر ارتقای نسخه و restore از backup تست شده است؟

اشتباهات رایج

  • تست روی SQLite و deploy روی MySQL یا MariaDB بدون اجرای migrationها روی همان دیتابیس.
  • استفاده از latin1 یا utf8 سه‌بایتی برای فارسی به‌جای utf8mb4.
  • فرض یکسان بودن optimizer یا رفتار JSON در هر دو بدون تست.
  • restore مستقیم dump از MySQL 8 روی MariaDB بدون بررسی collation.
  • تکیه بر عدد benchmark عمومی به‌جای اندازه‌گیری با دادهٔ خودتان.
  • ارتقای major نسخهٔ دیتابیس روی production بدون backup و تست روی staging.

جمع‌بندی

برای Laravel هر دو انتخاب معتبرند، اما یکسان نیستند. محصول و نسخه‌ای را انتخاب کنید که production واقعاً ارائه می‌دهد، درایور mysql یا mariadb را مطابق آن تنظیم کنید، محیط‌ها را یکسان نگه دارید و هر جابه‌جایی را با backup و staging انجام دهید. مهم‌تر از نام دیتابیس: index درست، backup قابل restore و env امن. نصب: XAMPP.

طراحی دیتابیس پروژه — مشاوره دهید.

اشتراک‌گذاری