بار اول که این خطا را در یک پروژه جدی دیدم، در یک فروشگاه ووکامرسی بود که هنگام ذخیره محصول جدید، با پیام مبهم Got error 28 from storage engine مواجه می‌شد. آن روز ابتدا فکر کردم مسئله از افزونه است، ولی وقتی به سرور SSH زدم و فضای دیسک را بررسی کردم، فهمیدم که پارتیشن /var/lib/mysql پر شده و MySQL نمی‌تواند فایل موقت بنویسد. از آن روز، هر بار این خطا را می‌بینم، پیش از هر چیز به عدد خطا و لایه فیزیکی سرور می‌روم، نه به کد افزونه.

خطای Got error from storage engine دقیقاً چیست؟

خطای Got error N from storage engine یکی از پیام‌های استاندارد MySQL است که زمانی ظاهر می‌شود که لایه موتور ذخیره‌سازی (storage engine) نمی‌تواند یک عملیات درخواستی را تکمیل کند و به‌جای توضیح دقیق، تنها یک کد عددی برمی‌گرداند. پیام کامل آن معمولاً به‌شکل زیر است:

ERROR 1030 (HY000): Got error 28 from storage engine
ERROR 1030 (HY000): Got error 168 from storage engine
ERROR 1030 (HY000): Got error -1 from storage engine

بخش 1030 کد اصلی خطا در MySQL است و بخش from storage engine نشان می‌دهد که خطا از لایه پایین‌دستی آمده. مهم‌ترین نکته این است که این خطا یک پیام کلی است: MySQL دقیقاً نمی‌گوید چه چیزی شکست خورده، بلکه فقط می‌گوید «موتور ذخیره‌سازی یک خطا برگرداند» و شما را به شماره خطا ارجاع می‌دهد. درک معنای این شماره، کلید تشخیص است. اگر با خانواده خطاهای MySQL آشنایی کامل ندارید، پیشنهاد می‌کنم ابتدا مرور جامعی روی ساختار آن داشته باشید؛ مقاله «آموزش mysql از صفر» نقطه شروع مناسبی است.

نکته ظریف این است که این خطا از دو لایه متفاوت می‌تواند بیاید: در پروژه‌هایی که از موتور MySQL استفاده می‌کنند، ممکن است پیام از موتور MyISAM، از موتور InnoDB، یا از لایه‌های میانی مثل سیستم فایل سرور آمده باشد. به همین دلیل، تشخیص دقیق نیازمند بررسی کد خطا و لاگ سرور است، نه فقط نگاه به پیام.

این خطا یک پیام لایه‌ای است: MySQL فقط می‌گوید مشکل از موتور ذخیره‌سازی است؛ پیدا کردن ریشه، وظیفه شماست.

یکی از پرتکرارترین مواردی که در تجربه‌ام به آن برخورده‌ام، اشتباه گرفتن این خطا با Table is marked as crashed است. در آن خطا، جدول مشخصاً شکسته علامت می‌خورد؛ در این خطا، MySQL مشکل را به لایه پایین‌تر ارجاع می‌دهد. برای درک دقیق‌تر این تفاوت، مرور «خطای Table is marked as crashed» توصیه می‌شود؛ چون مرز بین این دو خطا، یکی از پرتکرارترین موارد سردرگمی در دیباگ است.

کدهای عددی این خطا و معنای هر کدام

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

کد خطامعنای تقریبیلایه ریشه
28فضای دیسک تمام شدهلایه سیستم فایل
168مشکل در نوشتن روی دیسکلایه I/O
-1خطای عمومی موتورلایه موتور
144جدول شکسته یا ناقصلایه موتور
121مشکل در دیسک یا I/Oلایه سیستم فایل
126فایل ایندکس باز نشدلایه موتور
134جدول پر شده یا محدودیت رسیدهلایه موتور
136رکورد خراب یا ناسازگارلایه موتور

نکته مهمی که در تجربه من بیش از همه به آن برخورده‌ام، این است که کد ۲۸ (فضای دیسک) یکی از پرتکرارترین دلایل این خطا در پروژه‌های واقعی است. به همین دلیل، اولین کاری که بعد از دیدن این خطا انجام می‌دهم، بررسی فضای دیسک سرور است. اگر فضای دیسک در محدوده خطر باشد، هر اقدام دیگری بی‌اثر است و فقط علت اصلی حل می‌شود.

کد ۱۶۸ (مشکل در نوشتن روی دیسک) در سناریوهایی رخ می‌دهد که دیسک فضای کافی دارد، ولی نمی‌تواند عملیات نوشتن را تکمیل کند. دلایل این حالت می‌تواند شامل خرابی سکتور، مشکل در سیستم فایل، یا محدودیت‌های سطح سیستم‌عامل باشد.

کدهای دسته ۱۲۰ تا ۱۳۹ (مثل ۱۲۱، ۱۲۶، ۱۳۴، ۱۳۶) معمولاً مربوط به لایه موتور ذخیره‌سازی هستند و نشان می‌دهند که فایل‌های جدول در وضعیت ناسالم قرار دارند. در این موارد، معمولاً نیاز به ترمیم جدول یا بازگردانی از پشتیبان است.

برای مرور دقیق‌تر دستورات مدیریتی MySQL که در این نوع بررسی‌ها به کار می‌آید، مرور «دستورات پرکاربرد mysql» توصیه می‌شود؛ چون یکی از گام‌های تشخیص، اجرای دستورات SHOW ENGINE و CHECK TABLE است.

کد عددی خطا، کلید تشخیص است؛ بدون آن، پیام مبهم باقی می‌ماند.

موتور ذخیره‌سازی در کدام لایه قرار دارد؟

برای این‌که بتوانید این خطا را در ریشه رفع کنید، باید مکانیزم پایین‌دستی آن را بلد باشید. MySQL از یک معماری لایه‌ای استفاده می‌کند که در آن، لایه SQL روی یک لایه میانی به‌نام storage engine سوار می‌شود. این لایه، وظیفه مدیریت فیزیکی داده‌ها روی دیسک را بر عهده دارد. سه لایه اصلی این معماری عبارتند از:

  1. لایه SQL: در این لایه، کوئری‌های SQL پارس می‌شوند و به عملیات سطح موتور تبدیل می‌شوند.
  2. لایه موتور ذخیره‌سازی: در این لایه، عملیات خواندن و نوشتن روی فایل‌های داده و ایندکس انجام می‌شود.
  3. لایه سیستم فایل: در این لایه، عملیات نهایی روی دیسک فیزیکی انجام می‌شود.

خطای Got error from storage engine در لایه دوم رخ می‌دهد؛ یعنی موتور ذخیره‌سازی نتوانسته عملیات درخواستی را تکمیل کند. در بعضی موارد، ریشه در لایه سوم قرار دارد (مثل پر شدن فضای دیسک)، ولی خطا از لایه دوم گزارش می‌شود چون موتور ذخیره‌سازی اولین لایه‌ای است که این مشکل را تشخیص می‌دهد.

در پروژه‌های مدرن، موتور ذخیره‌سازی اصلی InnoDB است. این موتور، برخلاف MyISAM، از سیستم‌های ژورنالینگ و تراکنش‌های پیچیده استفاده می‌کند و همین ویژگی‌ها باعث می‌شوند که احتمال شکستگی و خطا در آن کمتر باشد. با این حال، در سناریوهای خاص مثل خرابی سخت‌افزار یا پر شدن دیسک، جداول InnoDB هم می‌توانند با این خطا مواجه شوند. برای درک دقیق‌تر تفاوت موتورها در این بافت، مرور «تفاوت innodb و myisam» توصیه می‌شود؛ چون این تفاوت، مسیر تشخیص و درمان را کاملاً تغییر می‌دهد.

نکته کاربردی مهم: در MySQL 8، موتور MyISAM به‌عنوان موتور منسوخ (deprecated) علامت خورده و تیم MySQL توصیه می‌کند که همه جداول به InnoDB مهاجرت کنند. ولی در پروژه‌های قدیمی، هنوز جداول MyISAM وجود دارند و همین جداول، منبع اصلی خطای فعلی هستند.

موتور ذخیره‌سازی، لایه میانی بین SQL و سیستم فایل است؛ خطا در آن، معمولاً از لایه‌های زیرین ناشی می‌شود.

تفاوت با خطاهای Table is marked as crashed و Disk full

یکی از پرتکرارترین سؤالاتی که در جلسات بازبینی کد زیاد می‌شنوم این است: تفاوت این خطا با Table is marked as crashed و Disk full چیست؟ پاسخ در ظاهر ساده است ولی در عمل مهم: اولی خطای لایه موتور است، دومی خطای لایه جدول، و سومی خطای لایه سیستم فایل.

برای این‌که در پروژه‌های چندخطایی بتوانید سریع تشخیص دهید کدام خطا را پیش رو دارید، بد نیست اعضای پرتکرار این خانواده را کنار هم ببینید:

پیاملایه خطامعنای دقیق
Got error from storage engineلایه موتورموتور ذخیره‌سازی پاسخ نداد
Table is marked as crashedلایه جدولجدول در وضعیت ناسالم است
Disk fullلایه سیستم فایلفضای دیسک تمام شده
Can't create/write to fileلایه فایلنوشتن روی فایل ممکن نیست
Unknown storage engineلایه تنظیماتموتور درخواست‌شده پشتیبانی نمی‌شود
Table does not existلایه وجودجدول در دیتابیس وجود ندارد

تفاوت کلیدی این خطا با Table is marked as crashed در این است که در خطای فعلی، جدول مشخصاً شکسته علامت نخورده و فقط لایه موتور پاسخ نداده. گاهی این وضعیت به شکستگی جدول منتهی می‌شود ولی همیشه این‌طور نیست. به همین دلیل، در این خطا، ابتدا باید سراغ لاگ سرور و کد خطا رفت، نه سراغ جدول.

در لایه وجود جدول، خطای Table does not exist زمانی رخ می‌دهد که جدول مقصد در دیتابیس وجود نداشته باشد. این خطا در نگاه اول شبیه خطای فعلی به نظر می‌رسد، ولی ماهیتش کاملاً متفاوت است. برای درک دقیق‌تر این تفاوت، مرور «رفع خطای Table doesn't exist در MySQL» توصیه می‌شود؛ چون مرز بین این دو خطا، یکی از پرتکرارترین موارد اشتباه در دیباگ است.

در لایه دسترسی، خطای Access denied زمانی رخ می‌دهد که کاربر MySQL به آن عملیات دسترسی نداشته باشد. اگر با این خطا مواجه شدید، مرور «خطای Access denied for user در MySQL» توصیه می‌شود؛ چون در بعضی پرونده‌ها، این دو خطا در کنار هم دیده می‌شوند.

در تجربه من، پرونده‌های Got error from storage engine در پنج کلاس اصلی جای می‌گیرند: فضای دیسک تمام شده؛ مشکل I/O در سرور؛ جدول شکسته در موتور MyISAM؛ محدودیت‌های سطح موتور مثل innodb_log_file_size؛ و مشکل در فایل‌های موقت. اگر با این پنج کلاس آشنا باشید، بخش بزرگی از پرونده‌های این خطا را می‌توانید سریع تحلیل کنید.

هشت سناریوی واقعی که این خطا را فعال می‌کنند

در پرونده‌هایی که به من رسیده، تعداد الگوهایی که به این خطا منتهی می‌شوند بیشتر از آن‌چه انتظار می‌رود است. هشت سناریوی زیر، تقریباً همه پرونده‌های عملی را پوشش می‌دهند.

سناریو اول: پر شدن فضای دیسک

شایع‌ترین حالت. وقتی پارتیشن مربوط به MySQL پر می‌شود، موتور ذخیره‌سازی نمی‌تواند فایل موقت یا فایل داده بنویسد و خطای ۲۸ برمی‌گرداند. راه‌حل، آزاد کردن فضا و در بلندمدت، مانیتورینگ فضای دیسک است:

df -h
du -sh /var/lib/mysql/

سناریو دوم: مشکل I/O در دیسک

اگر دیسک سرور با مشکل سخت‌افزاری مواجه شود، عملیات نوشتن نمی‌تواند تکمیل شود و خطای ۱۶۸ یا مشابه آن برمی‌گردد. راه‌حل، بررسی سلامت دیسک با ابزارهایی مثل smartctl و در صورت نیاز، جایگزینی دیسک است.

سناریو سوم: جدول شکسته MyISAM

در موتور MyISAM، اگر جدول در عملیات قبلی شکسته باشد، هر کوئری روی آن با خطای ۱۴۴ یا مشابه برمی‌گردد. راه‌حل، ترمیم با REPAIR TABLE یا myisamchk است. برای مرور دقیق‌تر این فرآیند، مرور «خطای Table is marked as crashed در MySQL» توصیه می‌شود.

سناریو چهارم: محدودیت‌های سطح موتور InnoDB

در InnoDB، اگر innodb_log_file_size یا innodb_buffer_pool_size به‌درستی تنظیم نشده باشد، عملیات سنگین می‌تواند با خطای موتور مواجه شود. راه‌حل، تنظیم دقیق این پارامترها بر اساس حجم داده و بار سرور است.

سناریو پنجم: مشکل در فایل‌های موقت

در بعضی سناریوها، موتور ذخیره‌سازی نمی‌تواند فایل موقت ایجاد کند، چون مسیر موقت قابل نوشتن نیست. راه‌حل، بررسی مجوزهای مسیر /tmp و اطمینان از فضای کافی است.

سناریو ششم: خرابی در فایل‌های جدول

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

سناریو هفتم: مشکل در فایل‌سیستم سرور

در بعضی سناریوها، فایل‌سیستم سرور در وضعیت ناسالم قرار دارد و نمی‌تواند عملیات I/O را به‌درستی انجام دهد. راه‌حل، بررسی با ابزارهای مثل fsck و در صورت نیاز، بازگردانی سیستم فایل است.

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

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

ulimit -n
SHOW VARIABLES LIKE 'open_files_limit';
در همه هشت سناریو، یک نکته مشترک وجود دارد: لایه‌ای زیر موتور ذخیره‌سازی، نتوانسته عملیات را تکمیل کند.

دام اختصاصی وردپرس و ووکامرس

در تجربه من، بخش بزرگی از پرونده‌های Got error from storage engine مربوط به پروژه‌های وردپرسی و ووکامرسی است. دلیلش روشن است: این سیستم‌ها در نسخه‌های قدیمی، از موتور MyISAM برای بعضی جداول کلیدی استفاده می‌کردند و در به‌روزرسانی‌های مختلف، بار سنگینی روی موتور ذخیره‌سازی تحمیل می‌شود.

ریشه تاریخی در وردپرس

وردپرس تا نسخه ۴.۲، برای جداول خود از موتور MyISAM استفاده می‌کرد. از نسخه ۴.۲ به بعد، این موتور به InnoDB تغییر یافت، ولی این تغییر فقط در نصب‌های جدید اعمال می‌شد. برای نصب‌های قدیمی، تیم وردپرس یک فرآیند ارتقای اختیاری طراحی کرد. اگر این فرآیند در پروژه شما انجام نشده، جداول شما همچنان روی MyISAM هستند و در معرض خطای موتور قرار دارند.

بررسی موتور جداول وردپرس

برای بررسی موتور جداول وردپرس، می‌توانید از کوئری زیر استفاده کنید:

SELECT table_name, engine
FROM information_schema.tables
WHERE table_schema = 'your_wp_database'
  AND table_name LIKE 'wp_%';

اگر مقادیر این ستون شامل MyISAM باشد، پروژه شما در معرض خطای موتور است.

مهاجرت از MyISAM به InnoDB در وردپرس

برای مهاجرت جداول وردپرس به InnoDB، می‌توانید از دستور زیر استفاده کنید:

ALTER TABLE wp_posts ENGINE = InnoDB;

توصیه من این است که این کار را جدول‌به‌جدول و در ساعات کم‌ترافیک انجام دهید. پیش از هر تغییر، بکاپ کامل دیتابیس ضروری است. برای مرور دقیق‌تر روش‌های پشتیبان‌گیری در بافت وردپرس، مرور «چگونه از سایت وردپرسی بکاپ بگیریم» و «بهترین افزونه‌های پشتیبان‌گیری وردپرس» توصیه می‌شود.

دام ووکامرس

در ووکامرس، جداول سفارشات و محصولات از موتور InnoDB استفاده می‌کنند، ولی جداول کش، لاگ و گزارش‌گیری ممکن است روی MyISAM باشند. اگر این جداول شکسته شوند یا موتور ذخیره‌سازی نتواند آن‌ها را باز کند، فرآیند نمایش محصولات یا ثبت سفارش مختل می‌شود. راه‌حل، ترمیم سریع جدول مشکل‌دار و سپس مهاجرت به InnoDB است. برای مرور دقیق‌تر افزونه‌های استاندارد در ووکامرس، مرور «بهترین افزونه‌های کاربردی برای ووکامرس» توصیه می‌شود؛ چون انتخاب افزونه‌های استاندارد، از بسیاری از این مشکلات جلوگیری می‌کند.

چطور ریشه این خطا را در پروژه ایزوله کنیم؟

فرض کنید همین امروز یک خطای Got error from storage engine در محیط تولید ظاهر شده و می‌خواهید ریشه‌اش را پیدا کنید. روشی که در این نوع پرونده‌ها به کار می‌گیرم، شش گام دارد و هر گام، یک شرط را در ذهن من حذف می‌کند.

گام اول: نگاه دقیق به کد عددی خطا

اولین کاری که می‌کنم، خواندن دقیق کد عددی خطا است. اگر کد ۲۸ باشد، مسئله فضای دیسک است؛ اگر کد ۱۶۸ باشد، مسئله I/O؛ اگر کد ۱۴۴ یا ۱۳۴ باشد، مسئله موتور؛ و اگر کد ۱۲۰ تا ۱۳۹ باشد، مسئله فایل‌های جدول. این تفکیک اولیه، مسیر دیباگ را کاملاً تغییر می‌دهد.

گام دوم: بررسی فضای دیسک

دومین کاری که می‌کنم، بررسی فضای دیسک است:

df -h
du -sh /var/lib/mysql/

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

گام سوم: بررسی لاگ خطا MySQL

سومین کاری که می‌کنم، بررسی لاگ خطا MySQL است:

tail -n 200 /var/log/mysql/error.log
tail -n 200 /var/log/mysqld.log

این لاگ، دلیل دقیق خطا را نشان می‌دهد. اگر دلیل، خطای I/O یا مشکل جدول باشد، معمولاً در لاگ ثبت شده است.

گام چهارم: بررسی وضعیت جداول

چهارمین کاری که می‌کنم، بررسی وضعیت جداول است:

CHECK TABLE wp_posts, wp_options, wp_postmeta;

اگر جدولی علامت corrupt یا crashed داشت، باید ابتدا ترمیم شود.

گام پنجم: بررسی وضعیت موتور ذخیره‌سازی

پنجمین کاری که می‌کنم، بررسی وضعیت موتور ذخیره‌سازی است:

SHOW ENGINE INNODB STATUS\G
SHOW ENGINE MYISAM STATUS\G

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

گام ششم: بررسی سلامت سخت‌افزار

ششمین کاری که می‌کنم، بررسی سلامت سخت‌افزار است:

smartctl -a /dev/sda
dmesg | grep -i error

اگر خرابی سخت‌افزار گزارش شود، ترمیم جدول فقط راه‌حل موقت است و باید به فکر جایگزینی سخت‌افزار باشید. در کنار این شش گام، یک تکنیک عملی مهم وجود دارد: در بافت ORMها مثل Eloquent یا SQLAlchemy، اگر موتور ذخیره‌سازی مشکل داشته باشد، خطای اصلی در لایه پایین‌تر رخ می‌دهد و ORM فقط پیام کلی برمی‌گرداند. توصیه من این است که همیشه در لایه دیتابیس، وضعیت موتور را بررسی کنید.

راه‌حل‌های امن و ترتیب درست عملیات

بعد از تشخیص، نوبت به رفع است. شش الگوی عملی در پروژه‌ها به کارم آمده که هر کدام، در بافت متفاوتی مناسب است.

الگوی اول: آزاد کردن فضای دیسک

ساده‌ترین و در بسیاری از پروژه‌ها کافی‌ترین راه‌حل، آزاد کردن فضای دیسک است:

# حذف لاگ‌های قدیمی
find /var/log -name '*.log' -mtime +30 -delete

# پاک‌سازی بکاپ‌های قدیمی
find /var/backups -name '*.sql' -mtime +7 -delete

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

الگوی دوم: ترمیم جدول مشکل‌دار

اگر جدول مشخصاً شکسته باشد، ترمیم آن ضروری است:

REPAIR TABLE wp_options;
REPAIR TABLE wp_options EXTENDED;

برای جدول‌های MyISAM، این روش استاندارد است. برای جدول‌های InnoDB، باید از روش‌های دیگر مثل innodb_force_recovery استفاده کرد.

الگوی سوم: بازگردانی از پشتیبان

در بعضی سناریوها، ترمیم نتیجه نمی‌دهد و بهترین راه‌حل، بازگردانی از پشتیبان است:

mysql -u user -p your_db < backup.sql

توصیه من این است که پیش از بازگردانی، از وضعیت فعلی هم یک نسخه پشتیبان بگیرید تا در صورت لزوم، قابل مقایسه باشد. برای مرور دقیق‌تر استراتژی‌های پشتیبان‌گیری، مرور «پشتیبان گیری از mysql» توصیه می‌شود.

الگوی چهارم: تنظیم پارامترهای موتور

در بعضی سناریوها، تنظیم درست پارامترهای موتور می‌تواند از خطا جلوگیری کند:

SET GLOBAL innodb_buffer_pool_size = 2G;
SET GLOBAL innodb_log_file_size = 256M;

توصیه من این است که این تغییرات را با احتیاط و در محیط توسعه ابتدا تست کنید.

الگوی پنجم: بررسی و افزایش محدودیت‌ها

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

ulimit -n 65535

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

الگوی ششم: مهاجرت به موتور InnoDB

در بلندمدت، مهاجرت از MyISAM به InnoDB توصیه می‌شود:

ALTER TABLE wp_posts ENGINE = InnoDB;

در انتخاب بین این شش الگو، هیچ‌کدام را نباید به‌عنوان نسخه «درست» در نظر گرفت؛ انتخاب، به بافت پروژه و اندازه تیم بستگی دارد. برای مرور جامع‌تر الگوهای مدیریت خطا در بافت دیتابیس، مطالعه «بهینه سازی کوئری های mysql» توصیه می‌شود.

حذف کامل این خطا از سیستم، نتیجه ترکیب چند الگوی طراحی است، نه یک توصیه تک‌خطی.

الگوهای پیشگیری در کد مدرن

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

الگوی اول: پایش منظم فضای دیسک

تیم‌های حرفه‌ای، فضای دیسک سرور را به‌طور منظم پایش می‌کنند و در آستانه ۷۰ درصد، هشدار می‌دهند:

df -h | awk '$5+0 > 70 {print}'

این الگو، از خطای ۲۸ که شایع‌ترین حالت است، جلوگیری می‌کند.

الگوی دوم: استانداردسازی موتور جداول

در پروژه‌های مدرن، همه جداول با موتور InnoDB ساخته می‌شوند. این استاندارد، احتمال خطای موتور را به‌شکل چشمگیری کم می‌کند.

الگوی سوم: تست پایداری در CI/CD

در پروژه‌های بالغ، پایداری جداول در فرآیند CI/CD تست می‌شود. اگر جدولی مشکل داشته باشد، قبل از استقرار شناسایی می‌شود.

الگوی چهارم: مستندسازی الگوهای خطا

در پروژه‌های بالغ، خطاهای رایج و راه‌حل‌های آن‌ها در مستندات پروژه ثبت می‌شوند. این مستندات، پاسخ سریع در زمان بروز خطا را ممکن می‌کند.

الگوی پنجم: استفاده از تلمتری متمرکز

در پروژه‌های مدرن، خطاهای دیتابیس در یک سیستم تلمتری متمرکز ثبت می‌شوند. این کار، امکان تحلیل الگوهای خطا را در بلندمدت فراهم می‌کند.

الگوی ششم: آموزش تیم فنی

در تیم‌های بالغ، همه اعضای تیم با خطاهای رایج MySQL آشنا هستند و می‌توانند در زمان بروز حادثه، اقدامات اولیه را انجام دهند. در انتخاب بین این شش الگو، هیچ‌کدام را نباید به‌عنوان نسخه «درست» در نظر گرفت؛ انتخاب، به بافت پروژه و اندازه تیم بستگی دارد. برای مرور جامع‌تر الگوهای بهینه‌سازی، مطالعه «بهینه‌سازی جداول MySQL برای سرعت بیشتر» توصیه می‌شود.

اشتباهات رایجی که این خطا را تشدید می‌کنند

در بررسی پرونده‌های این خطا، هفت اشتباه تکراری دیده‌ام که هر کدام، به‌جای رفع مشکل، آن را پیچیده‌تر می‌کند.

  • نادیده گرفتن کد عددی خطا. کد خطا، کلید تشخیص است. اگر آن را نادیده بگیرید، در پیچ‌وخم پیام مبهم می‌مانید.
  • ترمیم بدون بررسی فضای دیسک. اگر فضای دیسک پر باشد، ترمیم هم نتیجه نمی‌دهد. ابتدا فضا را آزاد کنید.
  • اجرای REPAIR TABLE روی InnoDB. این دستور روی InnoDB کار نمی‌کند و پیام خطا می‌دهد. برای InnoDB باید از ابزارهای دیگر استفاده کرد.
  • استفاده از kill -9 برای خاموش کردن MySQL. این روش، اجازه نمی‌دهد MySQL فایل‌ها را به‌درستی ببندد. همیشه از دستورات استاندارد استفاده کنید.
  • بازگردانی از پشتیبان بدون تست. اگر پشتیبان تست نشده باشد، ممکن است در زمان بازگردانی، خودش منبع خطای جدید باشد.
  • نادیده گرفتن سلامت سخت‌افزار. اگر دیسک سرور خراب باشد، ترمیم‌های مکرر فقط زمان می‌برند و ریشه حل نمی‌شود.
  • عدم مستندسازی الگوهای خطا. اگر تیم فنی نداند که در زمان بروز خطا چه گام‌هایی باید برداشت، هر توسعه‌دهنده به سلیقه خود عمل می‌کند.

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

ماتریس تست پایداری موتور ذخیره‌سازی

چیزی که در پروژه‌های بالغ به‌شکل منظم دیده‌ام، تست‌های اختصاصی برای پایداری موتور است. ماتریسی که در پروژه‌ها استفاده می‌کنم، این شکلی است:

سناریوورودیخروجی مورد انتظار
بررسی سلامت جدول سالمCHECK TABLEOK
بررسی سلامت جدول مشکل‌دارCHECK TABLEcorrupt یا crashed
بررسی فضای دیسکdf -hفضای کافی
بررسی وضعیت موتورSHOW ENGINE INNODB STATUSوضعیت سالم
ترمیم جدول MyISAMREPAIR TABLEOK
مهاجرت به InnoDBALTER TABLE ... ENGINE = InnoDBموفقیت
خطای فضای دیسکGot error 28آزاد کردن فضا
خطای I/OGot error 168بررسی سخت‌افزار
خطای موتور MyISAMGot error 144ترمیم جدول

هر ردیف از این ماتریس، یک سناریوی واقعی را پوشش می‌دهد. اگر این تست‌ها را در پروژه خود بگذارید، نه‌فقط خطاهای زمان اجرا را زودتر می‌گیرید، بلکه وقتی تیم شما بزرگ‌تر می‌شود، رفتار برنامه در برابر تغییرات، قابل پیش‌بینی می‌ماند.

یک تذکر مهم: در تست‌های پایداری، مطمئن شوید که همه لایه‌ها (موتور جدول، تنظیمات سرور، فرآیند پشتیبان‌گیری) با هم‌خوانی یکسان تست می‌شوند. برای مرور دقیق‌تر این بافت، مرور «ایندکس گذاری در mysql» و «تراکنش ها در mysql» توصیه می‌شود.

پرسش‌های پرتکرار درباره Got error from storage engine

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

این خطا از کد می‌آید یا از دیتابیس؟

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

کد ۲۸ چه معنایی دارد؟

کد ۲۸ به معنای «فضای دیسک تمام شده» است. این شایع‌ترین کد این خطا است. راه‌حل، آزاد کردن فضای دیسک سرور است.

کد ۱۶۸ چه معنایی دارد؟

کد ۱۶۸ به معنای «مشکل در نوشتن روی دیسک» است. این کد در سناریوهای خرابی سکتور یا مشکل سیستم فایل رخ می‌دهد.

تفاوت این خطا با Table is marked as crashed چیست؟

اولی خطای لایه موتور است، دومی خطای لایه جدول. برای بررسی دقیق‌تر، مرور «خطای Table is marked as crashed در MySQL» توصیه می‌شود.

آیا در InnoDB هم این خطا رخ می‌دهد؟

بله، ولی نادر است. در InnoDB، اگر خرابی سخت‌افزار یا پر شدن دیسک رخ دهد، ممکن است این خطا ظاهر شود.

چطور بفهمم کدام موتور ذخیره‌سازی مشکل دارد؟

با کوئری زیر می‌توانید موتور جداول را بررسی کنید:

SELECT table_name, engine
FROM information_schema.tables
WHERE table_schema = 'your_database';

آیا REPAIR TABLE همیشه جواب می‌دهد؟

خیر. این دستور فقط برای جداول MyISAM کار می‌کند. برای InnoDB باید از روش‌های دیگر مثل innodb_force_recovery استفاده کرد.

آیا این خطا روی MariaDB هم رخ می‌دهد؟

بله. MariaDB نیز از همان مکانیزم موتور ذخیره‌سازی استفاده می‌کند و همین خطا در آن هم دیده می‌شود.

آیا در هاست اشتراکی می‌توانم این خطا را برطرف کنم؟

در بعضی هاست‌ها، دسترسی به تنظیمات موتور وجود ندارد. در این حالت، باید با پشتیبانی هاست تماس بگیرید و مشکل را گزارش کنید.

چطور از این خطا پیشگیری کنم؟

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

نگاه معمارانه: پایداری موتور به‌عنوان قرارداد

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

لایه اول: استانداردسازی موتور و پارامترها

تیم‌های حرفه‌ای برای همه جداول، یک موتور استاندارد (InnoDB) و پارامترهای استاندارد انتخاب می‌کنند. این استاندارد، در مستندات پروژه ثبت می‌شود و در بازبینی کد اجرا می‌شود. با این استاندارد، هیچ‌کس به‌طور تصادفی از موتور متفاوت یا پارامتر اشتباه استفاده نمی‌کند.

لایه دوم: پایش خودکار و هشدار

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

لایه سوم: تست خودکار پایداری

در پروژه‌های بالغ، پایداری موتور در فرآیند CI/CD تست می‌شود. یعنی پیش از استقرار، یک تست ساده اجرا می‌شود که از سلامت موتور و جداول مطمئن شود. اگر در آن تست، خطایی گزارش شود، استقرار متوقف می‌شود. این لایه، جلوی بسیاری از خطاهای موتور را در تولید می‌گیرد.

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

وقتی پایداری موتور به‌عنوان یک قرارداد سراسری دیده شود، از یک تنظیم محلی به یک تعهد سازمانی تبدیل می‌شود.

یک تصمیم کوچک، یک کلاس خطای ازیادرفته

خطای Got error from storage engine در نگاه اول یک خطای مبهم به‌نظر می‌رسد، اما در عمل، آینه‌ای است که نشان می‌دهد لایه پایداری داده پروژه شما چقدر صریح و کنترل‌شده است. اگر این خطا در تولید ظاهر می‌شود، به احتمال زیاد جای دیگری از سیستم هم فضای دیسک یا پارامترهای موتور در محدوده خطر قرار دارد. به همین دلیل، توصیه عملی من سه چیز است: اول، همیشه کد عددی خطا را جدی بگیرید و بر اساس آن، لایه ریشه را تشخیص دهید؛ دوم، در مرزهای سیستم، یک لایه پایش خودکار برای فضای دیسک و وضعیت موتور بگذارید؛ سوم، در تست‌های خود ماتریس سناریوهای پایداری موتور را بگنجانید تا رفتار برنامه در برابر خرابی‌های ناگهانی، قابل پیش‌بینی بماند.

اگر خطای مشابهی را در یک پروژه واقعی تجربه کرده‌اید — مخصوصاً جایی که ریشه مشکل از آنچه انتظار داشتید دور بوده — تجربه‌تان را در دیدگاه بنویسید. برای من جالب است بدانم کدام کد خطا بیشترین دردسر را ایجاد کرده، و آیا الگویی پیدا کردید که با آنچه در این متن آمده، تفاوت داشت. تجربه‌های واقعی شما، این متن را برای خواننده بعدی دقیق‌تر می‌کند. 🗄️