اولین بار که خطای Unknown database در MySQL را در یک پروژه‌ی زنده دیدم، تازه یک migration بزرگ را روی سرور staging اجرا کرده بودم. همه‌چیز بی‌نقص به‌نظر می‌رسید، ولی صبح روز بعد، اپلیکیشن با پیام ساده‌ای بالا نیامد: Unknown database 'mydb_production'. تا آن روز، این خطا را یک مشکل تایپی می‌دانستم که با بررسی نام دیتابیس حل می‌شود. آن روز فهمیدم که خطای Unknown database در MySQL، در ظاهر یک خطای ساده به‌نظر می‌رسد ولی در باطن، پنجره‌ای است به سمت مدل ذخیره‌سازی دیتابیس در MySQL، مدیریت چرخه‌ی حیات دیتابیس، تفاوت محیط‌ها، و معماری درست جداسازی داده و کد.

خطای Unknown database در MySQL دقیقاً چیست؟

MySQL به‌عنوان یکی از محبوب‌ترین سیستم‌های مدیریت دیتابیس رابطه‌ای، داده‌ها را در واحدهایی به نام دیتابیس سازماندهی می‌کند. هر دیتابیس، یک namespace مجزا با مجموعه‌ای از جداول، viewها، stored procedureها و triggerها است. وقتی اپلیکیشن شما در رشته‌ی اتصال (connection string) نام یک دیتابیس را مشخص می‌کند، MySQL بررسی می‌کند که آن دیتابیس در آن سرور وجود دارد یا نه. اگر وجود نداشته باشد، خطای زیر مطرح می‌شود:

ERROR 1049 (42000): Unknown database 'mydb'

# یا در PDO

SQLSTATE[HY000] [1049] Unknown database 'mydb'

# یا در اپلیکیشن‌های وب

Database mydb not found

پیام خطا سه داده‌ی مهم دارد: کد خطا (1049)، SQLSTATE (42000)، و نام دیتابیسی که جستجو شده. ترکیب این سه، جهت تشخیص را از ابتدا روشن می‌کند. اگر با مبانی MySQL آشنایی ندارید، ابتدا یادگیری MySQL از صفر را بخوانید تا مدل ذهنی درستی از ساختار دیتابیس شکل بگیرد.

نکته‌ی مهم این است که این خطا در لایه‌ی مجوزدهی رخ می‌دهد، نه در لایه‌ی احراز هویت و نه در لایه‌ی شبکه. یعنی MySQL کاربر را شناخته، اتصال را پذیرفته، ولی دیتابیس مورد نظر را پیدا نکرده است. این تفکیک، در تشخیص سریع کمک‌کننده است.

خطای Unknown database یک شکایت از وجود است، نه از دسترسی. MySQL می‌گوید تو درست وارد شدی، ولی آن اتاقی که دنبالش هستی، در این ساختمان وجود ندارد. راه‌حل، بررسی نام و مکان است نه رمز.

تفاوت این خطا با Access denied و Can't connect

یکی از پرتکرارترین سؤالات تازه‌کارها، تفاوت سه خطای اصلی MySQL است. درک درست این تفاوت، اولین گام در تشخیص سریع است:

Can't connect to MySQL server: خطای لایه‌ی شبکه. یعنی MySQL در آن آدرس و پورت در دسترس نیست. دلایل: سرویس خاموش، پورت اشتباه، فایروال، یا bind-address.

Access denied for user: خطای لایه‌ی احراز هویت و مجوزدهی. یعنی MySQL در دسترس است ولی اعتبار کاربر رد شده یا کاربر به دیتابیس دسترسی ندارد. دلایل: رمز اشتباه، هاست اشتباه، یا مجوز ناکافی.

Unknown database: خطای لایه‌ی مجوزدهی سطح دیتابیس. یعنی اتصال برقرار شده و کاربر شناخته شده، ولی دیتابیس مورد نظر در آن سرور وجود ندارد. دلایل: تایپی در نام، حذف دیتابیس، یا اتصال به سرور اشتباه.

جدول زیر تفاوت این سه خطا را خلاصه می‌کند:

خطا لایه ریشه راه‌حل
Can't connect شبکه سرویس، پورت، فایروال بررسی اتصال شبکه
Access denied احراز هویت / مجوز رمز، هاست، مجوز اصلاح کاربر و مجوزها
Unknown database مجوزدهی سطح دیتابیس نام دیتابیس، محیط ایجاد یا اصلاح نام دیتابیس

جزئیات کامل دو خطای دیگر در خطای Can't connect to MySQL server و خطای Access denied for user در MySQL آمده است.

کدهای خطا و پیام‌های مختلف

خطای Unknown database در نسخه‌های مختلف MySQL و در لایه‌های مختلف، پیام‌های متفاوتی دارد. شناخت این تفاوت‌ها، در تشخیص سریع کمک‌کننده است:

کد خطا پیام منبع
1049 Unknown database 'dbname' MySQL server
1044 Access denied for user to database MySQL server (مجوز)
1045 Access denied for user (using password) MySQL server (احراز هویت)
SQLSTATE 42000 Syntax error or access rule violation SQL استاندارد
2003 Can't connect to MySQL server لایه شبکه
1046 No database selected MySQL server

نکته‌ی ظریف: خطای No database selected (1046) با خطای Unknown database (1049) متفاوت است. اولی یعنی شما از یک کوئری استفاده کردید ولی هیچ دیتابیسی انتخاب نشده. دومی یعنی دیتابیسی که انتخاب شده، وجود ندارد. جزئیات کامل سایر خطاهای MySQL در خطاهای رایج MySQL آمده است.

MySQL چگونه دیتابیس را پیدا می‌کند؟

برای درک درست خطای Unknown database، باید مکانیزم جستجوی دیتابیس در MySQL را بشناسیم. MySQL سه مرحله را طی می‌کند:

مرحله اول: بررسی نام. وقتی اپلیکیشن با USE dbname یا mysql_select_db() یا در رشته‌ی اتصال، نام دیتابیس را مشخص می‌کند، MySQL آن نام را در پوشه‌ی datadir جستجو می‌کند. این پوشه معمولاً در /var/lib/mysql/ است. هر دیتابیس، یک پوشه با نام خودش دارد.

مرحله دوم: بررسی مجوزها. MySQL جدول mysql.db را بررسی می‌کند که آیا کاربر فعلی مجاز به دسترسی به آن دیتابیس است یا نه.

مرحله سوم: فعال‌سازی. اگر دیتابیس پیدا شد و کاربر مجاز بود، MySQL آن را فعال می‌کند. اگر پیدا نشد، خطای Unknown database می‌دهد. اگر پیدا شد ولی کاربر مجاز نبود، خطای Access denied می‌دهد.

نکته‌ی مهم: در MySQL، نام دیتابیس به بزرگی و کوچکی حروف حساس است روی Linux/Unix. روی Windows و macOS که فایل‌سیستم case-insensitive دارند، این تفاوت دیده نمی‌شود. این موضوع در بخش‌های بعدی به‌تفصیل بررسی شده است.

در MySQL 8.x، لایه‌ی جدیدی به نام data dictionary اضافه شده که اطلاعات متادیتا را در خود MySQL نگهداری می‌کند، نه در فایل‌سیستم. این تغییر، سرعت و دقت جستجو را بهبود داده ولی در نسخه‌های قدیمی، جستجو از طریق فایل‌سیستم انجام می‌شود.

چرا MySQL این خطا را مطرح می‌کند؟

MySQL به‌طور طراحی‌شده، خطای Unknown database را در شرایطی مطرح می‌کند که اپلیکیشن درخواست دسترسی به دیتابیسی می‌کند که در آن سرور وجود ندارد. این تصمیم، از چند اصل بنیادین می‌آید:

یک: جداسازی فضای نام (namespace). MySQL از دیتابیس‌ها به‌عنوان namespace استفاده می‌کند. این رویکرد، از تصادم نام جدول‌ها بین دیتابیس‌های مختلف جلوگیری می‌کند. اگر نام دیتابیس اشتباه باشد، MySQL نمی‌تواند آن را به namespace درست نگاشت کند.

دو: بازخورد سریع. اگر اپلیکیشن درخواست دسترسی به دیتابیسی می‌کند که وجود ندارد، بهتر است سریع خطا بدهد تا کاربر مدت طولانی منتظر نماند. MySQL با خطای واضح Unknown database این بازخورد سریع را فراهم می‌کند.

سه: امنیت. MySQL اجازه نمی‌دهد اپلیکیشن به دیتابیس‌های غیرموجود دسترسی پیدا کند. این تصمیم امنیتی، از رفتارهای غیرمنتظره جلوگیری می‌کند. اگر MySQL به‌جای خطا، دیتابیس را خودکار ایجاد می‌کرد، ممکن بود فضای ذخیره‌سازی سرور بی‌دلیل مصرف شود.

در چارچوب کلی MySQL، خطای Unknown database بخشی از ساختار دفاعی این دیتابیس است. این خطا، شما را وادار می‌کند درباره‌ی نام دیتابیس، محیط اجرا، و چرخه‌ی حیات دیتابیس صریح باشید. همین فلسفه در سایر خطاهای MySQL مثل خطای Can't connect to MySQL server هم دیده می‌شود.

هشت علت رایج خطای Unknown database

در تجربه‌ی من روی صدها پروژه‌ی MySQL، خطای Unknown database از هشت علت مشخص می‌آید. شناخت این علت‌ها، تشخیص را در چند ثانیه ممکن می‌کند.

  1. اشتباه تایپی در نام دیتابیس: شایع‌ترین علت.
  2. دیتابیس هرگز ایجاد نشده است: در پروژه‌های جدید یا بعد از پاک‌سازی.
  3. اتصال به سرور اشتباه: اپلیکیشن به MySQL دیگری متصل شده.
  4. حساسیت به بزرگی و کوچکی حروف: تفاوت بین MyDB و mydb.
  5. پیشوند اجباری در هاست اشتراکی: نام دیتابیس با پیشوند نام اکانت.
  6. دیتابیس حذف یا تغییر نام داده شده: در طول چرخه‌ی حیات پروژه.
  7. مشکل در انتقال بین محیط‌ها: دیتابیس staging در production وجود ندارد.
  8. مشکل در Docker و Kubernetes: نام دیتابیس اشتباه یا سرویس آماده نیست.

هر علت، نشانه‌های مخصوص به خود و راه‌حل اختصاصی دارد. در بخش‌های بعدی، هر علت را جداگانه باز می‌کنم.

اشتباه تایپی در نام دیتابیس

شایع‌ترین منبع خطای Unknown database، اشتباه تایپی در نام دیتابیس است. الگوی کلاسیک:

# در .env
DB_NAME=wordpres_db   # اشتباه (به‌جای wordpress_db)

# در wp-config.php
define("DB_NAME", "wordpres_db");  # اشتباه

# در Django settings.py
DATABASES = {
    "default": {
        "NAME": "myapp_db_",  # کاراکتر اضافی
    }
}

نکته‌ی مهم: MySQL به بزرگی و کوچکی حروف حساس است. یعنی WordPress_DB، wordpress_db، و WORDPRESS_DB سه دیتابیس متفاوت هستند. این مشکل در تیم‌هایی که به‌طور معمول از نام‌های camelCase یا snake_case استفاده می‌کنند، شایع‌تر است.

راه‌حل: بررسی نام دقیق دیتابیس از طریق MySQL CLI:

-- لیست دیتابیس‌ها
SHOW DATABASES;
# یا
SHOW DATABASES LIKE "%wordpress%";

# خروجی
# +--------------------+
# | Database           |
# +--------------------+
# | wordpress_db       |
# | wordpress_db_test  |
# +--------------------+

سپس نام دقیق را در فایل پیکربندی اپلیکیشن قرار دهید. برای جلوگیری از این مشکل، از یک منبع واحد برای نام دیتابیس استفاده کنید (مثلاً فایل .env) و همه‌ی بخش‌های اپلیکیشن، همان نام را از این فایل بخوانند. مبانی کار با دیتابیس در طراحی دیتابیس در MySQL آمده است.

دیتابیس هرگز ایجاد نشده است

دومین منبع شایع، عدم ایجاد دیتابیس است. این حالت در شرایط زیر رخ می‌دهد:

  • پروژه‌ی جدید. دیتابیس هنوز ایجاد نشده.
  • پروژه‌ی clone شده. از یک مخزن کلون شده ولی دیتابیس مربوطه ایجاد نشده.
  • سرور جدید. اپلیکیشن روی سرور جدید اجرا می‌شود ولی دیتابیس منتقل نشده.
  • نصب خودکار ناقص. اسکریپت نصب خودکار دیتابیس را ایجاد نکرده.

نشانه‌ها:

ERROR 1049 (42000): Unknown database 'mydb'

mysql> SHOW DATABASES;
# +--------------------+
# | Database           |
# +--------------------+
# | information_schema |
# | mysql              |
# | performance_schema |
# | sys                |
# +--------------------+
# mydb در لیست نیست

راه‌حل: ایجاد دیتابیس با CREATE DATABASE:

CREATE DATABASE mydb
    CHARACTER SET utf8mb4
    COLLATE utf8mb4_unicode_ci;

-- بررسی ایجاد
SHOW DATABASES LIKE "mydb";

نکته‌ی ظریف: انتخاب character set و collation مناسب، در ابتدای ایجاد دیتابیس اهمیت دارد. تغییر آن بعداً، دردسرهای زیادی ایجاد می‌کند. برای پروژه‌های فارسی و چندزبانه، utf8mb4 با utf8mb4_unicode_ci توصیه می‌شود. مبانی کامل در یادگیری MySQL از صفر آمده است.

اتصال به سرور اشتباه

سومین منبع شایع، اتصال به سرور اشتباه است. الگوی کلاسیک:

# در .env
DB_HOST=staging-db.example.com  # ولی دیتابیس در production-db.example.com است
DB_NAME=mydb

در این مثال، اپلیکیشن به سرور staging متصل می‌شود ولی دیتابیس mydb در آن سرور وجود ندارد. خطای Unknown database می‌دهد.

نشانه‌ها:

  • دیتابیس در سرور فعلی وجود دارد، ولی اپلیکیشن خطا می‌دهد.
  • اتصال با mysql -h correct-host -u user -p mydb کار می‌کند ولی اپلیکیشن خطا می‌دهد.
  • در لاگ اپلیکیشن، هاست اشتباه ثبت شده است.

راه‌حل: بررسی هاست واقعی در فایل پیکربندی:

# در .env
DB_HOST=10.0.0.5    # یا hostname دقیق

# تست اتصال از CLI
mysql -h 10.0.0.5 -u dbuser -p -e "SHOW DATABASES LIKE 'mydb';"

نکته‌ی ظریف: در محیط‌هایی که چند سرور دیتابیس دارند (multi-cluster)، خطای Unknown database می‌تواند ناشی از load balancer باشد که درخواست را به سرور اشتباه هدایت می‌کند. راه‌حل: بررسی لاگ load balancer و تنظیم routing مناسب. مبانی سرور در سرور چیست و چگونه کار می‌کند آمده است.

حساسیت به بزرگی و کوچکی حروف

چهارمین منبع، حساسیت به بزرگی و کوچکی حروف است. در MySQL روی Linux/Unix، نام دیتابیس به بزرگی و کوچکی حروف حساس است. یعنی:

-- اشتباه: نام با حروف بزرگ نوشته شده
CREATE DATABASE WordPress_DB;

-- اپلیکیشن: نام با حروف کوچک
USE wordpress_db;
-- ERROR 1049 (42000): Unknown database 'wordpress_db'

این مشکل، به‌ویژه در تیم‌هایی که توسعه‌دهندگان روی macOS یا Windows کار می‌کنند و سرور production روی Linux است، شایع است. چون در macOS و Windows، فایل‌سیستم case-insensitive است، تفاوت دیده نمی‌شود. ولی روی Linux، نام‌ها متمایز هستند.

نکته‌ی مهم در MySQL 8.x: تنظیم lower_case_table_names تعیین می‌کند که MySQL به بزرگی و کوچکی حساس باشد یا نه:

SHOW VARIABLES LIKE "lower_case_table_names";

# 0 = case-sensitive (پیش‌فرض Linux)
# 1 = case-insensitive (پیش‌فرض Windows/macOS)
# 2 = case-sensitive ولی ذخیره lowercase (macOS خاص)

راه‌حل: استانداردسازی نام دیتابیس به lowercase در سراسر پروژه. این رویکرد، از تفاوت‌های بین سیستم‌عامل‌ها جلوگیری می‌کند. مبانی کامل در یادگیری MySQL از صفر آمده است.

پیشوند اجباری در هاست اشتراکی

پنجمین منبع، پیشوند اجباری در هاست‌های اشتراکی است. در cPanel و DirectAdmin، نام دیتابیس معمولاً با پیشوند نام اکانت هاست شروع می‌شود:

# در cPanel
نام اکانت: myaccount
نام دیتابیس: myaccount_wordpress_db

# در فایل پیکربندی اپلیکیشن
DB_NAME=wordpress_db  # اشتباه
DB_NAME=myaccount_wordpress_db  # درست

در این مثال، اپلیکیشن نام wordpress_db را وارد کرده، ولی دیتابیس واقعی myaccount_wordpress_db است. MySQL دیتابیس wordpress_db را پیدا نمی‌کند و خطا می‌دهد.

راه‌حل: بررسی نام کامل دیتابیس از پنل هاست. در cPanel، بخش MySQL Databases، نام کامل دیتابیس و کاربر را نشان می‌دهد. کپی دقیق همان نام در فایل پیکربندی. مبانی cPanel در cPanel چیست و چه کاربردی دارد آمده است.

نکته‌ی ظریف: در بعضی هاست‌ها، محدودیت تعداد کاراکتر نام دیتابیس وجود دارد. مثلاً نام نباید بیشتر از 16 کاراکتر باشد (بدون احتساب پیشوند). این محدودیت‌ها می‌توانند باعث شوند که نام انتخابی شما کوتاه شود و اپلیکیشن نام دیگری جستجو کند. مبانی هاست در هاست چیست و چگونه انتخاب کنیم آمده است.

دیتابیس حذف یا تغییر نام داده شده

ششمین منبع، حذف یا تغییر نام دیتابیس است. این حالت در شرایط زیر رخ می‌دهد:

  • حذف تصادفی. کسی دستور DROP DATABASE را اجرا کرده.
  • تغییر نام. دیتابیس rename شده ولی اپلیکیشن به‌روز نشده.
  • مهاجرت ناقص. دیتابیس قدیمی حذف شده ولی جدید به‌درستی کپی نشده.
  • تمیزکاری ناخواسته. در جریان پاک‌سازی سرور، دیتابیس غیرضروری تشخیص داده شده و حذف شده.

نشانه‌ها:

-- بررسی تاریخچه در MySQL
SHOW DATABASES;
# mydb در لیست نیست ولی جداول در بکاپ وجود دارند

# بررسی بکاپ
ls -la /var/backups/mysql/
# backup_mydb_20260915.sql

راه‌حل:

راه اول: بازیابی از بکاپ

# ایجاد دیتابیس جدید
CREATE DATABASE mydb CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

# بازیابی از بکاپ
mysql -u root -p mydb < /var/backups/mysql/backup_mydb_20260915.sql

راه دوم: بررسی log باینری

# اگر MySQL binlog فعال است
mysqlbinlog /var/log/mysql/mysql-bin.000123 | grep -i "drop database"

نکته‌ی پیشگیرانه: هرگز دیتابیس را بدون بررسی حذف نکنید. حذف دیتابیس، برگشت‌ناپذیر است. مبانی پشتیبان‌گیری در پشتیبان‌گیری از MySQL آمده است.

دیتابیس بین محیط‌ها منتقل نشده

هفتمین منبع، عدم انتقال دیتابیس بین محیط‌ها است. این مشکل در جریان توسعه، به‌ویژه در جریان CI/CD شایع است:

  • دیتابیس staging در production وجود ندارد.
  • دیتابیس development در staging وجود ندارد.
  • مشکل در اسکریپت migration. اسکریپت اجرا شده ولی دیتابیس را ایجاد نکرده.

نشانه‌ها:

# در CI/CD pipeline
mysql -h $DB_HOST -u $DB_USER -p$DB_PASS -e "SHOW DATABASES;"
# mydb در لیست نیست

# اجرای migration
python manage.py migrate
# Unknown database 'mydb'

راه‌حل: اسکریپت ایجاد دیتابیس در ابتدای migration:

#!/bin/bash
# setup_db.sh
mysql -h $DB_HOST -u $DB_USER -p$DB_PASS -e "
    CREATE DATABASE IF NOT EXISTS $DB_NAME
    CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"

# سپس migration
python manage.py migrate

نکته‌ی ظریف: در محیط‌های Docker، می‌توانید دیتابیس را با MYSQL_DATABASE در environment variables ایجاد کنید. این رویکرد در docker-compose.yml و Kubernetes manifest مناسب است. مبانی CI/CD در مباحث مربوطه آمده است.

Unknown database در Docker و Kubernetes

هشتمین منبع، مربوط به Docker و Kubernetes است. در این محیط‌ها، خطای Unknown database از منابع خاص خود می‌آید:

در Docker

# docker-compose.yml
services:
  db:
    image: mysql:8
    environment:
      MYSQL_ROOT_PASSWORD: root_pass
      MYSQL_DATABASE: mydb  # نام دیتابیس ایجاد شده
      MYSQL_USER: dbuser
      MYSQL_PASSWORD: user_pass
  app:
    environment:
      DB_HOST: db
      DB_NAME: mydb  # باید با MYSQL_DATABASE یکی باشد
      DB_USER: dbuser

مشکل شایع: MYSQL_DATABASE و DB_NAME متفاوت هستند. راه‌حل: هر دو را با یک نام تنظیم کنید یا از یک متغیر مشترک استفاده کنید.

مشکل شایع دوم: ترتیب اجرای containerها. اگر اپلیکیشن قبل از آماده شدن MySQL اجرا شود، خطای Unknown database می‌دهد چون دیتابیس هنوز ایجاد نشده:

services:
  app:
    depends_on:
      - db
    # ولی depends_on فقط ترتیب اجرا را تضمین می‌کند، نه آمادگی
    # راه‌حل: استفاده از wait-for-it یا healthcheck

  db:
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
      interval: 5s
      timeout: 5s
      retries: 10

در Kubernetes

# در StatefulSet MySQL
env:
  - name: MYSQL_DATABASE
    valueFrom:
      configMapKeyRef:
        name: db-config
        key: database
  - name: MYSQL_ROOT_PASSWORD
    valueFrom:
      secretKeyRef:
        name: db-secret
        key: root-password

# در اپلیکیشن Deployment
env:
  - name: DB_NAME
    valueFrom:
      configMapKeyRef:
        name: app-config
        key: db-name  # باید با MYSQL_DATABASE یکی باشد

نکته‌ی مهم در Kubernetes: استفاده از ConfigMap و Secret برای تنظیمات مشترک بین MySQL و اپلیکیشن. این رویکرد، از ناهماهنگی نام دیتابیس جلوگیری می‌کند. مبانی Kubernetes در مباحث مربوط به orchestration آمده است.

Unknown database در وردپرس

در وردپرس، خطای Unknown database با پیام زیر نمایش داده می‌شود:

Error establishing a database connection
# یا در صفحه:
Unknown database 'wordpress_db'

سه دلیل اصلی:

  1. نام دیتابیس در wp-config.php اشتباه است.
  2. دیتابیس در سرور وجود ندارد.
  3. پیشوند اکانت هاست در نام دیتابیس لحاظ نشده.

راه‌حل: بررسی و اصلاح اطلاعات اتصال در wp-config.php:

define("DB_NAME", "myaccount_wordpress_db");  # نام کامل
define("DB_USER", "myaccount_dbuser");
define("DB_PASSWORD", "your_password");
define("DB_HOST", "localhost");

برای بررسی اینکه دیتابیس واقعاً وجود دارد، از phpMyAdmin یا MySQL CLI استفاده کنید:

mysql -u myaccount_dbuser -p -e "SHOW DATABASES;"

اگر دیتابیس وجود ندارد، آن را از cPanel ایجاد کنید. مبانی وردپرس در وردپرس چیست و چگونه شروع کنیم آمده است.

در PHP، PDO و mysqli

در PHP، خطای Unknown database از دو مسیر می‌آید:

در mysqli

$conn = new mysqli("localhost", "dbuser", "password", "mydb");
if ($conn->connect_error) {
    // Unknown database 'mydb'
    error_log($conn->connect_error);
}

در PDO

try {
    $pdo = new PDO(
        "mysql:host=localhost;dbname=mydb;charset=utf8mb4",
        "dbuser",
        "password"
    );
} catch (PDOException $e) {
    // SQLSTATE[HY000] [1049] Unknown database 'mydb'
    error_log($e->getMessage());
}

نکته‌ی ظریف: در PDO، اتصال در سازنده new PDO برقرار می‌شود. بنابراین خطای Unknown database در همین نقطه رخ می‌دهد، نه در اولین کوئری.

راه‌حل: بررسی نام دیتابیس قبل از اتصال، و مدیریت صریح خطا:

$dbName = getenv("DB_NAME");

// اعتبارسنجی نام
if (!preg_match("/^[a-zA-Z0-9_]+$/", $dbName)) {
    throw new InvalidArgumentException("Invalid database name");
}

try {
    $pdo = new PDO(
        "mysql:host=" . getenv("DB_HOST") . ";dbname=$dbName;charset=utf8mb4",
        getenv("DB_USER"),
        getenv("DB_PASSWORD")
    );
} catch (PDOException $e) {
    if ($e->getCode() === "1049") {
        error_log("Unknown database: " . $dbName);
    }
    throw $e;
}

این رویکرد، در پروژه‌های production، استاندارد است. مبانی کامل در آموزش PDO در PHP و اتصال PHP به MySQL آمده است.

در Django و Flask

در فریم‌ورک‌های وب پایتونی، خطای Unknown database از منابع خاص خود می‌آید:

در Django

# در settings.py
DATABASES = {
    "default": {
        "ENGINE": "django.db.backends.mysql",
        "NAME": "mydb",  # اگر در MySQL نباشد، خطا
        "USER": "dbuser",
        "PASSWORD": "password",
        "HOST": "127.0.0.1",
        "PORT": "3306",
    }
}

خطا در زمان اجرای migration یا اولین کوئری رخ می‌دهد:

python manage.py migrate
# django.db.utils.OperationalError: (1049, "Unknown database 'mydb'")

راه‌حل: ایجاد دیتابیس قبل از migration:

mysql -u root -p -e "
    CREATE DATABASE IF NOT EXISTS mydb
    CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"

مبانی کامل در آموزش جنگو برای مبتدیان آمده است.

در Flask

# در config.py
SQLALCHEMY_DATABASE_URI = "mysql+pymysql://dbuser:password@localhost/mydb"

راه‌حل: اطمینان از وجود دیتابیس در MySQL قبل از اجرای اپلیکیشن. مبانی Flask در آموزش فلسک در پایتون آمده است.

روش تشخیص اصولی در پنج گام

در تجربه‌ی من، تشخیص خطای Unknown database در چند دقیقه انجام می‌شود، اگر روش سیستماتیک داشته باشید:

گام اول: خواندن دقیق پیام خطا. پیام MySQL دقیقاً نام دیتابیس را می‌گوید. این نام را در فایل پیکربندی اپلیکیشن بررسی کنید.

گام دوم: لیست دیتابیس‌ها. از MySQL CLI یا phpMyAdmin، لیست دیتابیس‌های موجود را ببینید:

SHOW DATABASES;
SHOW DATABASES LIKE "%wordpress%";

گام سوم: بررسی فایل پیکربندی. فایل‌های .env، wp-config.php، settings.py، یا config.php را بررسی کنید. نام دیتابیس در همه‌ی فایل‌ها باید یکی باشد.

گام چهارم: تست اتصال از CLI. از سرور اپلیکیشن، اتصال را با همان نام دیتابیس تست کنید:

mysql -u dbuser -p -h host mydb
# اگر خطا داد: Unknown database

گام پنجم: بررسی لاگ MySQL. در بعضی موارد، لاگ MySQL اطلاعات بیشتری دارد:

tail -100 /var/log/mysql/error.log | grep "Unknown database"

ابزارهای تشخیص:

  • SHOW DATABASES: لیست دیتابیس‌ها.
  • mysql -u user -p -h host dbname: تست اتصال از CLI.
  • grep DB_NAME .env: بررسی فایل پیکربندی.
  • phpMyAdmin: مدیریت از طریق رابط گرافیکی.
  • لاگ MySQL: بررسی خطاها با جزئیات.

مبانی کامل دستورات MySQL در دستورات پرکاربرد MySQL آمده است.

راهبردهای رفع اصولی

بعد از تشخیص، نوبت به رفع می‌رسد. راهبردهای رفع، بر اساس نوع خطا متفاوت است:

راهبرد اول: ایجاد دیتابیس

اگر دیتابیس وجود ندارد:

CREATE DATABASE mydb
    CHARACTER SET utf8mb4
    COLLATE utf8mb4_unicode_ci;

سپس کاربر به دیتابیس مجوز لازم را بدهید:

GRANT ALL PRIVILEGES ON mydb.* TO "dbuser"@"localhost";
FLUSH PRIVILEGES;

راهبرد دوم: اصلاح نام در فایل پیکربندی

اگر دیتابیس وجود دارد ولی نام اشتباه است، فایل پیکربندی را اصلاح کنید:

# در .env
DB_NAME=correct_db_name  # نام دقیق از SHOW DATABASES

راهبرد سوم: بازیابی از بکاپ

اگر دیتابیس حذف شده است:

CREATE DATABASE mydb CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
mysql -u root -p mydb < backup_file.sql

راهبرد چهارم: استفاده از متغیرهای محیطی

به‌جای نوشتن نام دیتابیس در چند فایل، از یک منبع واحد استفاده کنید:

# در .env
DB_NAME=mydb

# در docker-compose.yml
environment:
  MYSQL_DATABASE: ${DB_NAME}
  # در اپلیکیشن
  DB_NAME: ${DB_NAME}

راهبرد پنجم: چک‌لیست پیش از استقرار

در جریان CI/CD، قبل از استقرار اپلیکیشن، وجود دیتابیس را بررسی کنید:

#!/bin/bash
# pre-deploy.sh

# بررسی اتصال به MySQL
if ! mysql -h $DB_HOST -u $DB_USER -p$DB_PASS -e "USE $DB_NAME;" 2>/dev/null; then
    echo "Unknown database: $DB_NAME. Creating..."
    mysql -h $DB_HOST -u $DB_USER -p$DB_PASS -e "
        CREATE DATABASE IF NOT EXISTS $DB_NAME
        CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"
fi

این رویکرد، از خطاهای Unknown database در محیط production جلوگیری می‌کند. مبانی پشتیبان‌گیری و بازگردانی در پشتیبان‌گیری از MySQL آمده است.

راهبرد ششم: استانداردسازی نام‌گذاری

در پروژه‌های تیمی، از یک استاندارد نام‌گذاری استفاده کنید:

  • همیشه lowercase: mydb به‌جای MyDB.
  • پیشوند اپلیکیشن: myapp_db، myapp_staging، myapp_test.
  • بدون کاراکتر خاص: فقط حروف کوچک، اعداد و underscore.
  • بدون فاصله: my_db به‌جای my db.

این رویکرد، از خطاهای تایپی و ابهام جلوگیری می‌کند.

این خطا در محیط production

در محیط production، خطای Unknown database ابعاد جدی‌تری دارد:

قطع کامل سرویس

اگر خطای Unknown database رخ دهد، اپلیکیشن نمی‌تواند به دیتابیس متصل شود. این یعنی تمام کاربران، با خطای 500 یا صفحه‌ی سفید مواجه می‌شوند. در فروشگاه‌های آنلاین، این مسئله به از دست دادن سفارش‌ها منجر می‌شود.

نشت اطلاعات

پیام خطا، نام دیتابیس واقعی را افشا می‌کند. اگر این پیام به کاربر نمایش داده شود، اطلاعات حساس افشا می‌شود. راه‌حل: در production، خطاها را در سطح اپلیکیشن به پیام عمومی تبدیل کنید:

try {
    $pdo = new PDO($dsn, $user, $pass);
} catch (PDOException $e) {
    error_log($e->getMessage());
    die("Service temporarily unavailable");
}

پایش و آلارم‌دهی

در production، خطای Unknown database باید به‌طور فوری به تیم فنی اطلاع داده شود. ابزارهایی مثل Sentry، Rollbar، و LogRocket این خطاها را جمع‌بندی می‌کنند. نکته: بخش بزرگی از این خطاها از عدم هماهنگی بین محیط‌ها (development، staging، production) می‌آید. راه‌حل: پایش مداوم اتصال دیتابیس.

پیشگیری با تست

  • Pre-deployment tests: تست اتصال دیتابیس قبل از استقرار.
  • Smoke tests: تست startup اپلیکیشن.
  • Health checks: پایش مداوم اتصال دیتابیس.
  • Migration tests: تست migrationها با دیتابیس واقعی.

مبانی بهینه‌سازی در بهینه‌سازی جداول MySQL آمده است.

اشتباهات رایج در برخورد با این خطا

در طول سال‌ها، الگوهای تکراری از اشتباهات دیده‌ام که هر کدام می‌تواند پروژه را به چالش بکشد:

اشتباه اول: ایجاد دیتابیس بدون بررسی

ایجاد دیتابیس جدید به‌جای بررسی وجود دیتابیس فعلی، می‌تواند باعث از دست رفتن داده شود. راه‌حل: اول SHOW DATABASES را بررسی کنید، سپس تصمیم بگیرید.

اشتباه دوم: نادیده گرفتن پیشوند هاست اشتراکی

در هاست‌های اشتراکی، فرض نکردن پیشوند نام دیتابیس، منبع شایع خطا است. راه‌حل: نام کامل دیتابیس را از پنل هاست کپی کنید.

اشتباه سوم: استفاده از نام‌های case-mixed

استفاده از نام‌های با حروف بزرگ و کوچک مخلوط (مثل MyDB) می‌تواند در محیط‌های Linux به خطا منجر شود. راه‌حل: همیشه lowercase.

اشتباه چهارم: نبود اسکریپت ایجاد دیتابیس در CI/CD

در جریان CI/CD، اگر اسکریپت ایجاد دیتابیس وجود نداشته باشد، هر بار که محیط جدید ایجاد می‌شود، خطا می‌دهید. راه‌حل: اسکریپت CREATE DATABASE IF NOT EXISTS در ابتدای pipeline.

اشتباه پنجم: عدم بررسی محیط

فرض اینکه محیط staging و production شبیه هم هستند، منبع شایع خطا است. راه‌حل: چک‌لیست صریح برای هر محیط.

اشتباه ششم: نبود مستندسازی

اگر نام دیتابیس‌ها در هر محیط مستند نشود، در صورت تغییر تیم، بازگردانی سرویس سخت می‌شود. راه‌حل: مستندسازی دقیق نام دیتابیس‌ها در ویکی تیم.

اشتباه هفتم: عدم بررسی لاگ MySQL

لاگ MySQL می‌تواند اطلاعات دقیق‌تری درباره‌ی خطا بدهد. راه‌حل: بررسی مداوم لاگ‌ها در حین دیباگ.

خطای Unknown database یک شکایت از وجود است، نه از دسترسی. MySQL می‌گوید تو درست وارد شدی، ولی اتاقی که دنبالش هستی وجود ندارد. راه‌حل، بررسی نام و مکان است نه رمز.

پرسش‌های پرتکرار درباره Unknown database

این پرسش‌ها از دل تجربه‌ی عملی و جلسات مشاوره جمع‌آوری شده‌اند. پاسخ هر کدام بر اساس سناریوهای واقعی است.

تفاوت Unknown database و Access denied چیست؟

Unknown database وقتی رخ می‌دهد که MySQL کاربر را شناخته ولی دیتابیس مورد نظر وجود ندارد. Access denied وقتی رخ می‌دهد که MySQL کاربر را نمی‌شناسد یا به دیتابیس مجوز ندارد. تفاوت: اولی مشکل وجود، دومی مشکل هویت. جزئیات کامل در خطای Access denied for user در MySQL آمده است.

چرا خطای Unknown database با پیام خطای متفاوت نمایش داده می‌شود؟

هر موتور و هر لایه، پیام متفاوتی می‌دهد. در MySQL CLI: ERROR 1049 (42000): Unknown database. در PDO: SQLSTATE[HY000] [1049] Unknown database. در Django: django.db.utils.OperationalError: (1049, "Unknown database"). مفهوم در همه یکسان است.

آیا MySQL به بزرگی و کوچکی حروف در نام دیتابیس حساس است؟

در Linux/Unix، بله. در Windows و macOS، نه (به‌طور پیش‌فرض). راه‌حل: استانداردسازی به lowercase در سراسر پروژه. برای بررسی، از دستور SHOW VARIABLES LIKE "lower_case_table_names"; استفاده کنید.

چگونه بفهمم که دیتابیس وجود دارد؟

با دستور SHOW DATABASES یا SHOW DATABASES LIKE "mydb". همچنین از phpMyAdmin یا MySQL Workbench می‌توانید استفاده کنید.

آیا می‌توانم با root دیتابیس‌ها را ببینم؟

بله، با دستور mysql -u root -p -e "SHOW DATABASES;". برای دیدن دیتابیس‌های یک کاربر خاص: SHOW DATABASES LIKE "user_%".

چگونه در وردپرس، این خطا را حل کنم؟

اول، از طریق phpMyAdmin یا CLI بررسی کنید که دیتابیس وجود دارد. سپس نام دقیق را در wp-config.php قرار دهید. اگر پیشوند اکانت هاست لازم است، آن را فراموش نکنید. مبانی وردپرس در وردپرس چیست و چگونه شروع کنیم آمده است.

چرا دیتابیس در staging هست ولی در production نه؟

چون در جریان استقرار، دیتابیس ایجاد نشده یا نام آن در فایل پیکربندی production اشتباه است. راه‌حل: چک‌لیست استقرار با تست ایجاد دیتابیس.

آیا error 1044 (Access denied to database) هم در همین دسته است؟

نه. خطای 1044 در لایه‌ی مجوزدهی رخ می‌دهد و به‌معنای عدم دسترسی کاربر به یک دیتابیس موجود است. خطای 1049 (Unknown database) به‌معنای عدم وجود دیتابیس است. تفاوت: اولی مشکل مجوز، دومی مشکل وجود.

چگونه در Docker، Unknown database را حل کنم؟

اطمینان از اینکه MYSQL_DATABASE در container دیتابیس با DB_NAME در اپلیکیشن یکی است. همچنین از depends_on با healthcheck استفاده کنید تا اپلیکیشن بعد از آمادگی دیتابیس اجرا شود.

آیا Unknown database می‌تواند ناشی از فایروال باشد؟

نه. خطای Unknown database از لایه‌ی MySQL می‌آید و ربطی به فایروال ندارد. اگر فایروال جلوی اتصال را بگیرد، خطای Can't connect می‌گیرید.

چگونه در Kubernetes، این خطا را حل کنم؟

استفاده از ConfigMap برای نام دیتابیس که بین MySQL و اپلیکیشن مشترک است. همچنین از initContainer برای انتظار آمادگی دیتابیس استفاده کنید.

آیا می‌توانم از MySQL Workbench برای حل این خطا استفاده کنم؟

بله. MySQL Workbench یک رابط گرافیکی است که امکان دیدن دیتابیس‌ها، اجرای کوئری، و بررسی ساختار را فراهم می‌کند. این ابزار برای دیباگ خطاهای اتصال مفید است.

چگونه در CI/CD، این خطا را پیشگیری کنم؟

در pipeline، قبل از استقرار اپلیکیشن، یک اسکریپت setup_db.sh اجرا کنید که CREATE DATABASE IF NOT EXISTS را اجرا می‌کند. این رویکرد از خطاهای Unknown database جلوگیری می‌کند.

آیا error 1046 (No database selected) با Unknown database فرق دارد؟

بله. خطای 1046 وقتی رخ می‌دهد که کوئری اجرا شود ولی هیچ دیتابیسی انتخاب نشده باشد. خطای 1049 وقتی رخ می‌دهد که دیتابیس انتخاب شده ولی وجود ندارد. راه‌حل 1046: USE dbname یا مشخص کردن دیتابیس در اتصال.

چرا بعد از انتقال سرور، این خطا را می‌گیرم؟

چون در سرور جدید، دیتابیس ایجاد نشده یا نام آن در فایل پیکربندی اشتباه است. راه‌حل: بکاپ دیتابیس قدیمی را روی سرور جدید بازیابی کنید و نام را در فایل پیکربندی اصلاح کنید.

آیا Unknown database روی performance تأثیر دارد؟

خود خطا در لحظه‌ی وقوع رخ می‌دهد. اگر مدیریت شود، از نظر performance هزینه‌ی ناچیزی دارد. ولی اگر اپلیکیشن در حلقه بی‌پایان تلاش کند، performance تحت تأثیر قرار می‌گیرد.

چگونه در Django، این خطا را حل کنم؟

اول، دیتابیس را ایجاد کنید. سپس migration را اجرا کنید. مثال:

mysql -u root -p -e "CREATE DATABASE mydb CHARACTER SET utf8mb4;"
python manage.py migrate

مبانی کامل در آموزش جنگو برای مبتدیان آمده است.

آیا می‌توانم از mysqladmin برای حل این خطا استفاده کنم؟

با mysqladmin می‌توانید دیتابیس ایجاد کنید:

mysqladmin -u root -p create mydb
mysqladmin -u root -p status

این رویکرد، جایگزین سبک برای CREATE DATABASE است.

آیا این خطا می‌تواند از کتابخانه‌ی شخص ثالث بیاید؟

کتابخانه‌های ORM مثل SQLAlchemy، Django ORM، یا Hibernate، در صورت نبود دیتابیس، خطای Unknown database می‌دهند. راه‌حل: تنظیمات اتصال را بررسی کنید و دیتابیس را ایجاد کنید.

چگونه در Flask، این خطا را حل کنم؟

در Flask با SQLAlchemy:

# در config.py
SQLALCHEMY_DATABASE_URI = "mysql+pymysql://user:pass@host/mydb"

# در app.py
with app.app_context():
    db.create_all()  # جداول را ایجاد می‌کند ولی دیتابیس را نه

نکته: db.create_all() دیتابیس را ایجاد نمی‌کند، فقط جداول را. باید دیتابیس را جداگانه ایجاد کنید. مبانی Flask در آموزش فلسک در پایتون آمده است.

چرا دیتابیس در MariaDB هست ولی در MySQL نه؟

MariaDB و MySQL دو سیستم جداگانه هستند، هرچند سازگار. اگر اپلیکیشن شما به MySQL متصل می‌شود ولی دیتابیس در MariaDB است، خطای Unknown database می‌گیرید. راه‌حل: تطبیق سرور و دیتابیس.

آیا می‌توانم دیتابیس را با نام متفاوتی بازیابی کنم؟

بله. برای بازیابی با نام متفاوت:

CREATE DATABASE new_name CHARACTER SET utf8mb4;
mysqldump -u root -p old_name | mysql -u root -p new_name

سپس نام را در فایل پیکربندی اپلیکیشن به‌روز کنید. مبانی کامل در پشتیبان‌گیری از MySQL آمده است.

آنچه از سال‌ها کار با MySQL آموختم

اگر بخواهم چکیده‌ی این سال‌ها را در چند جمله بگویم، سه اصل عملی دارم:

یک: خطای Unknown database یک سیگنال از ناهماهنگی است، نه از کد. هر بار که این خطا می‌بینید، به‌جای سرزنش اپلیکیشن، به نام دیتابیس، محیط اجرا، و پیشوندهای هاست نگاه کنید. در 90 درصد موارد، ریشه در ناهماهنگی بین فایل پیکربندی و MySQL است.

دو: استانداردسازی نام‌گذاری، سرمایه‌گذاری بلندمدت است. از یک استاندارد واحد برای نام دیتابیس در سراسر پروژه استفاده کنید: lowercase، بدون کاراکتر خاص، با پیشوند واضح. این رویکرد، از بخش بزرگی از خطاهای تایپی جلوگیری می‌کند.

سه: اسکریپت ایجاد دیتابیس، بیمه‌ی CI/CD است. در pipeline استقرار، یک اسکریپت CREATE DATABASE IF NOT EXISTS اجرا کنید. این رویکرد، از خطاهای Unknown database در محیط‌های جدید جلوگیری می‌کند و زمان دیباگ را چند برابر کاهش می‌دهد.

در کنار این سه اصل، یک هشدار عملی هم دارم: خطای Unknown database در نگاه اول یک مشکل ساده به‌نظر می‌رسد، ولی وقتی در چارچوب کلی معماری دیتابیس دیده شود، تبدیل به یک سیگنال می‌شود. این سیگنال می‌گوید که چرخه‌ی حیات دیتابیس و مدیریت محیط‌ها نیاز به بازنگری دارد. اگر این سیگنال را جدی بگیرید و ساختار مدیریت دیتابیس را تقویت کنید، پروژه‌ی شما در ماه‌های بعد پایدارتر خواهد بود.

هدف این مقاله، تمام‌کردن همه‌ی سناریوهای ممکن نبود. هدف، دادن یک چارچوب ذهنی برای تشخیص، پیشگیری و رفع این خطا بود. وقتی این چارچوب را درونی کنید، برخورد با خطای Unknown database از یک واکنش اضطراری به یک فرآیند منظم تبدیل می‌شود.

اگر خطای Unknown database در پروژه‌ی شما به شکلی ظاهر شده که با الگوهای این مقاله حل نشده، برای من جالب است بدانم کدام سناریو بود. تجربه‌ی خودتان را در دیدگاه‌ها بنویسید؛ به‌ویژه اگر راه‌حلی پیدا کرده‌اید که هنوز در این مقاله نیست. 🗄️