مقدمه

اولین باری که این خطا را در پنل یک مشتری دیدم، گزارش‌گیری ووکامرس بود که بعد از حدود ۳۰ ثانیه اجرا، نیمه‌کاره رها می‌شد. مدیر سایت فکر می‌کرد افزونه گزارش‌گیری مشکل دارد. اما وقتی وارد لاگ MySQL شدم، دقیقاً یک پیام تکراری در ده‌ها خط پشت سر هم خودنمایی می‌کرد: «Query execution was interrupted». بعد از چند روز بررسی، فهمیدم که ریشه مشکل، نه در افزونه و نه در سرور، بلکه در یک تنظیم پنهان MySQL به نام max_execution_time بود که توسط یک ابزار مدیریت هاست اعمال شده بود.

این خطا در تجربه من از آن دسته خطاهایی است که با علائم مبهم شروع می‌شود و اگر درست تحلیل نشود، ممکن است شما را ماه‌ها درگیر خودش کند. در این مقاله می‌خواهم دقیقاً بگویم این خطا از کجا می‌آید، چه تفاوتی با خطاهای هم‌خانواده مثل timeout اتصال یا KILL دستی دارد، و چه راهکارهایی برای حل ریشه‌ای آن وجود دارد.

خطای Query execution was interrupted دقیقاً چیست؟

پیام «Query execution was interrupted» (کد خطای 1317 در MySQL) یعنی کوئری‌ای که در حال اجرا بود، پیش از اینکه به‌طور طبیعی به پایان برسد، به‌اجبار متوقف شد. این توقف می‌تواند از طرف خود MySQL، از طرف ادمین سرور یا به دلیل تنظیمات سیستم مدیریت MySQL اعمال شود.

پیام کامل خطا معمولاً به یکی از شکل‌های زیر در لاگ یا در خروجی PHP ظاهر می‌شود:

ERROR 1317 (70100): Query execution was interrupted

یک اشتباه رایج این است که این خطا با خطای Lock wait timeout exceeded یا خطای Lost connection to MySQL server قاطی شود. در واقع این سه خطا از نظر ظاهر مشابهند اما از نظر ریشه‌ای کاملاً متفاوتند. در ادامه این تفاوت‌ها را دقیق بررسی خواهم کرد. تفاوت اصلی این است: در «Query execution was interrupted»، کوئری واقعاً در حال اجرا بوده و بعد قطع شده؛ در دو خطای دیگر، مشکل در سطح اتصال یا انتظار برای قفل رخ داده است.

نکته کلیدی که در سال‌ها تجربه یاد گرفته‌ام این است: این خطا همیشه نشانه یک مشکل نیست. گاهی اوقات، یک KILL QUERY کاملاً عمدی و درست، همین پیام را تولید می‌کند. بنابراین قبل از هر اقدامی، باید بدانید «چه کسی کوئری را کشته است» و «چرا».

Query execution was interrupted یعنی یک تصمیم بیرونی، اجرای کوئری را متوقف کرده؛ سؤال درست این است که «چه کسی و چرا» این تصمیم را گرفته است.

پنج ریشه اصلی این خطا

در تجربه‌ام، این خطا تقریباً همیشه یکی از پنج ریشه زیر را دارد. هر کدام امضای خاص خودش را دارد:

۱. KILL QUERY دستی یا خودکار

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

۲. max_execution_time (MySL 5.7.8+)

از نسخه 5.7.8 به بعد، MySQL پارامتری به نام max_execution_time اضافه کرده که بر حسب میلی‌ثانیه تنظیم می‌شود. اگر مقدار آن را روی مثلاً ۳۰۰۰۰ (۳۰ ثانیه) بگذارید، هر کوئری SELECT که بیش از این مدت اجرا شود، خودکار قطع می‌شود. این پارامتر به‌طور پیش‌فرض صفر است (یعنی بی‌نهایت)، اما بسیاری از هاست‌ها آن را تنظیم می‌کنند بدون اینکه اطلاع‌رسانی کنند.

SHOW VARIABLES LIKE 'max_execution_time';
-- خروجی: 30000 یعنی ۳۰ ثانیه

۳. Statement Timeout از طرف پروکسی

اگر سایت شما از یک CDN، Load Balancer یا سرور میانی (مثل ProxySQL) عبور می‌کند، ممکن است کوئری در لایه میانی به خاطر یک timeout، قطع شود. این نوع قطع معمولاً اثر انگشت مشخصی دارد: کوئری‌ای که مستقیم روی سرور دیتابیس به‌طور کامل اجرا می‌شود، از طریق پروکسی در وسط راه قطع می‌گردد.

۴. Restart یا Failover سرور

اگر سرور MySQL در حال ریستارت باشد یا یک عملیات Failover رخ دهد، تمام کوئری‌های در حال اجرا با همین پیام قطع می‌شوند. این حالت معمولاً با پیام‌های اضافی در لاگ MySQL همراه است.

۵. باگ در حافظه یا موتور ذخیره‌سازی

در موارد نادر، خطاهای سخت‌افزاری یا باگ در موتور ذخیره‌سازی می‌توانند باعث قطع ناگهانی کوئری شوند. این حالت معمولاً با هشدارهای اضافی در لاگ همراه است. برای مطالعه بیشتر درباره موتورهای ذخیره‌سازی، مقاله تفاوت InnoDB و MyISAM را توصیه می‌کنم.

نشانه‌ها و علائم تشخیص

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

  • کندی ناگهانی در صفحه‌های گزارش‌گیری: صفحاتی مثل گزارش فروش ووکامرس، داشبورد وردپرس یا Export داده‌ها معمولاً اولین قربانی هستند.
  • افزایش زمان اجرای کوئری‌ها بدون تغییر داده: اگر یک گزارش روی هزار رکورد قبلاً ۲ ثانیه طول می‌کشید و الان ۲۵ ثانیه، احتمالاً در حال نزدیک شدن به سقف max_execution_time است.
  • پرش‌های تصادفی در لاگ: پیام‌های «Query execution was interrupted» که با فاصله چند ساعت یا چند روز ظاهر می‌شوند.
  • Timeout در فرم‌های سنگین: اگر فرم‌های طولانی نیمه‌کاره رها می‌شوند، ممکن است کوئری پشت آن‌ها قطع شده باشد.

تشخیص دقیق: از کجا شروع کنیم؟

برای تشخیص دقیق، ترتیب زیر را در تجربه‌ام مفید یافته‌ام:

گام اول: بررسی پارامترهای جاری

اولین کاری که می‌کنم این است که ببینم چه تنظیماتی روی سرور فعال است:

SHOW VARIABLES LIKE 'max_execution_time';
SHOW VARIABLES LIKE 'wait_timeout';
SHOW VARIABLES LIKE 'interactive_timeout';
SHOW VARIABLES LIKE 'net_read_timeout';

هر کدام از این پارامترها می‌توانند مقصر باشند. اگر max_execution_time صفر نباشد، احتمالاً همان مقصر است.

گام دوم: بررسی کوئری‌های در حال اجرا

با دستور زیر می‌توانید ببینید کدام کوئری‌ها در حال اجرا هستند و چقدر طول کشیده‌اند:

SHOW FULL PROCESSLIST;

در خروجی، به ستون Time نگاه کنید. اگر کوئری‌ای وجود دارد که بیش از چند ثانیه در حال اجراست، همان کاندید قطع شدن است. برای مطالعه بیشتر درباره بهینه‌سازی این کوئری‌ها، مقاله بهینه‌سازی کوئری‌های MySQL را ببینید.

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

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

[Note] Aborted connection 42 to db: 'wordpress' user: 'root' host: 'localhost'
[Warning] Query execution was interrupted for thread 42

این خطوط به شما می‌گویند کدام نخ (Thread) و کدام کوئری قربانی شده است.

گام چهارم: بررسی ابزارهای هاست

در هاست‌های اشتراکی، معمولاً یک ابزار مدیریتی در cPanel یا DirectAdmin وجود دارد که تعداد کوئری‌های متوقف‌شده در ۲۴ ساعت گذشته را نشان می‌دهد. اگر این عدد بالاست، باید به سراغ بهینه‌سازی بروید — همان‌طور که در مقاله کاهش مصرف منابع هاست توضیح دادم.

تفاوت با خطاهای مشابه

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

خطاعلت اصلینشانه
Query execution was interruptedقطع کوئری در حال اجرالاگ به‌همراه KILL یا timeout
Lock wait timeout exceededانتظار طولانی برای قفلتراکنش قربانی، بدون قطع کوئری
Lost connection to MySQLقطع ارتباط شبکه‌ایخطای ارتباط، بدون اجرای کوئری
Deadlock foundچرخه انتظار قفلRollback خودکار تراکنش
MySQL server has gone awayقطع سرور میانیعدم دسترسی کامل به MySQL

دو نکته ظریف در این جدول وجود دارد. اول، خطای Deadlock همیشه خودکار حل می‌شود، اما خطای Query interrupted نیاز به دخالت دارد. دوم، خطای Lost connection نشانه یک مشکل زیرساختی است، در حالی که Query interrupted می‌تواند صرفاً یک تصمیم عمدی باشد. تشخیص درست این تفاوت‌ها، اولین قدم در حل صحیح است.

راه‌حل‌های عملی و گام‌به‌گام

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

راه‌حل فوری: افزایش max_execution_time

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

SET SESSION max_execution_time = 60000; -- ۶۰ ثانیه

در سطح سرور، نیاز به دسترسی ادمین دارید و باید در فایل پیکربندی MySQL تنظیم شود:

[mysqld]
max_execution_time = 60000

یک هشدار: اگر این مقدار را روی یک هاست اشتراکی افزایش دهید، ممکن است ادمین هاست ناراضی شود، چون یک کوئری سرکش می‌تواند منابع کل سرور را مصرف کند.

راه‌حل کوتاه‌مدت: KILL دستی کوئری‌های سرکش

اگر کوئری‌های سرکش روی سرور دارید که مرتب منابع را مصرف می‌کنند، می‌توانید آن‌ها را با دستور KILL QUERY متوقف کنید. این کار به شما فرصت می‌دهد تا ریشه مشکل را در کد پیدا کنید:

-- پیدا کردن شناسه نخ‌های سنگین
SELECT ID, USER, TIME, INFO FROM information_schema.PROCESSLIST 
WHERE TIME > 20 AND COMMAND != 'Sleep';

-- قطع یک کوئری خاص
KILL QUERY 42;

راه‌حل ساختاری: بهینه‌سازی کوئری

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

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

بازنویسی کوئری: کوئری‌های با زیرکوئری‌های تودرتوی زیاد، معمولاً با JOIN بازنویسی می‌شوند. اگر با JOIN آشنا نیستید، مقاله آموزش Join در MySQL نقطه شروع خوبی است.

محدودسازی نتایج: اگر گزارش شما فقط ۱۰۰ ردیف آخر را نشان می‌دهد، چرا کوئری باید کل جدول را اسکن کند؟ افزودن LIMIT و ORDER BY روی یک ایندکس مناسب، تفاوت چند برابری ایجاد می‌کند.

راه‌حل مقطعی: کش کردن نتایج سنگین

اگر کوئری‌ای ذاتاً سنگین است و به‌طور مرتب اجرا می‌شود، به‌جای اجرای هر بار، نتیجه را در یک جدول کش ذخیره کنید. برای گزارش‌های ووکامرس، افزونه‌هایی مثل WooCommerce Analytics از همین روش استفاده می‌کنند. اگر می‌خواهید روش اصولی را یاد بگیرید، مقاله بهینه‌سازی دیتابیس ووکامرس را ببینید.

استراتژی‌های پیشگیری

پیشگیری از این خطا، نیازمند نگاه معماری است. در تجربه‌ام، رعایت این نکات بیشترین بازدهی را داشته:

۱. تحلیل منظم کوئری‌های کند

پارامتر slow_query_log را فعال کنید و هر هفته کوئری‌های کند را بررسی کنید. این کار قبل از اینکه کوئری‌ها به سقف زمانی برسند، آن‌ها را شناسایی می‌کند:

SET GLOBAL slow_query_log = 'ON';
SET GLOBAL long_query_time = 2;
SET GLOBAL slow_query_log_file = '/var/log/mysql/slow.log';

۲. محدودسازی گزارش‌های بزرگ

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

۳. پایش مستمر خطا

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

grep "Query execution was interrupted" /var/log/mysql/error.log | tail -5

۴. جدا کردن گزارش‌گیری از سایت اصلی

اگر فروشگاه شما حجم بالایی دارد، گزارش‌گیری‌ها را روی یک دیتابیس Read Replica انجام دهید. این کار هم سرعت گزارش‌گیری را بالا می‌برد، هم سایت اصلی را از فشار کوئری‌های سنگین دور می‌کند.

۵. مانیتورینگ منابع هاست

اگر روی هاست اشتراکی هستید، پنل هاست معمولاً ابزارهایی برای مشاهده مصرف CPU و RAM دارد. اگر مصرف CPU مرتب روی سقف است، احتمالاً کوئری‌های سنگین در حال قطع شدن هستند. راهنمای تأثیر هاست بر سرعت سایت کمک می‌کند تشخیص دهید که آیا ارتقای هاست لازم است یا نه.

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

پرسش‌های پرتکرار درباره خطای Query Interrupted

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

در کوئری‌های SELECT، خیر؛ چون فقط یک عملیات خواندن نیمه‌کاره رها می‌شود و هیچ تغییری روی داده‌ها اعمال نمی‌شود. اما در کوئری‌های INSERT، UPDATE یا DELETE، اگر تراکنش در میانه راه قطع شود و به‌درستی مدیریت نشود، ممکن است داده‌ها نیمه‌کاره تغییر کنند. حتماً از تراکنش‌ها به‌درستی استفاده کنید.

چطور بفهمم چه کسی کوئری را کشته است؟

در لاگ MySQL، معمولاً قبل از پیام خطا، یک خط Aborted connection یا Killed thread وجود دارد. همچنین می‌توانید در لاگ سرور یا ابزارهای هاستینگ بررسی کنید که آیا یک اسکریپت نظارتی این کار را کرده است.

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

خیر. این خطا در هر سیستم مبتنی بر MySQL می‌تواند رخ دهد. اما در ووکامرس چون گزارش‌های سنگین روی جداول بزرگ (wp_postmeta و wp_wc_order_stats) اجرا می‌شوند، شایع‌تر است.

آیا افزایش max_execution_time روی هاست اشتراکی ممکن است؟

در سطح session، بله. در سطح سرور، نیاز به دسترسی ادمین دارید که روی هاست اشتراکی معمولاً در دسترس نیست. اگر هاست شما این امکان را نمی‌دهد، باید به سراغ بهینه‌سازی کوئری بروید.

آیا KILL QUERY با KILL CONNECTION تفاوت دارد؟

بله. KILL QUERY فقط کوئری جاری را متوقف می‌کند و اتصال باز می‌ماند؛ اما KILL CONNECTION کل اتصال را قطع می‌کند. برای تحلیل دقیق‌تر بدون از دست دادن session، همیشه از KILL QUERY استفاده کنید.

آیا می‌توانم این خطا را در سطح کد PHP مدیریت کنم؟

بله. با استفاده از try/catch روی PDOException می‌توانید کد خطای 1317 را تشخیص دهید و به‌جای نمایش خطای خام، پیام کاربرپسندتری نمایش دهید. برای مطالعه بیشتر درباره مدیریت خطاهای PHP، مقاله مدیریت خطا در PHP را ببینید.

کالبدشکافی فنی: درون موتور MySQL چه می‌گذرد؟

برای درک عمیق این خطا، باید بدانید MySQL چطور کوئری‌ها را مدیریت می‌کند. هر اتصال به MySQL، یک Thread (نخ) اختصاصی دارد که در فضای کاربری سرور اجرا می‌شود. وقتی یک کوئری ارسال می‌شود، این نخ مراحل زیر را طی می‌کند:

  1. Parse: تجزیه SQL و تبدیل به یک درخت منطقی
  2. Optimize: انتخاب بهترین پلن اجرا بر اساس ایندکس‌ها و آمار
  3. Execute: اجرای واقعی پلن روی موتور ذخیره‌سازی
  4. Fetch: بازگرداندن نتایج به کلاینت

وقتی یک KILL QUERY ارسال می‌شود، MySQL یک پرچم داخلی به‌نام KILL_QUERY را روی آن نخ تنظیم می‌کند. در نقاط استراتژیکی از اجرای پلن (به‌طور معمول در پایان هر مرحله اجرا)، MySQL این پرچم را بررسی می‌کند. اگر پرچم فعال باشد، اجرای کوئری متوقف می‌شود و به کلاینت پیام ERROR 1317 بازگردانده می‌شود.

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

نکته مهم و کمتر شناخته‌شده: در تراکنش‌های InnoDB، KILL QUERY فقط کوئری جاری را متوقف می‌کند و تراکنش را Rollback نمی‌کند. یعنی ممکن است یک تراکنش نیمه‌کاره باقی بماند که قفل‌هایش باز نشده باشد. این موضوع می‌تواند به خطاهای Deadlock یا Lock Wait Timeout بعدی منجر شود. به همین دلیل، اگر برنامه شما با تراکنش‌ها کار می‌کند، پس از یک KILL QUERY، باید وضعیت تراکنش را با SHOW ENGINE INNODB STATUS بررسی کنید.

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

نقش هاست اشتراکی در بروز این خطا

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

سقف منابع CPU و I/O

هاست‌های اشتراکی معمولاً سقف CPU و I/O دارند. اگر کوئری شما به‌طور غیرعادی سنگین باشد، ممکن است هاست به‌طور خودکار آن را قطع کند. این کار معمولاً در لاگ به‌عنوان Resource limit reached همراه است. راهکار اصولی این است که کوئری را بهینه کنید — همان‌طور که در مقاله کاهش مصرف منابع هاست توضیح دادم. اگر به‌طور مرتب با این محدودیت روبه‌رو هستید، احتمالاً وقت ارتقای هاست است. برای انتخاب هاست مناسب، راهنمای انتخاب هاست به شما کمک می‌کند.

Statement Timeout اجباری

بعضی هاست‌های اشتراکی یک max_statement_time یا max_execution_time اجباری دارند که با ابزارهای پنل قابل تغییر نیست. برای بررسی، از دستور SHOW VARIABLES استفاده کنید. اگر مقدار صفر نبود و امکان تغییر نداشتید، دو گزینه پیش روی شماست: بهینه‌سازی کوئری یا مهاجرت به هاست حرفه‌ای‌تر. روش اصولی مهاجرت را در مهاجرت سایت به هاست جدید نوشته‌ام.

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

مطالعه موردی: بازگرداندن گزارش‌های ووکامرس

یک فروشگاه ووکامرسی با ۱۲۰۰۰ سفارش در ماه، با مشکل جالبی مواجه شد: گزارش‌های ماهانه در پنل ووکامرس، بعد از ۲۵ تا ۳۰ ثانیه به‌طور تصادفی می‌شکستند. مدیر سایت فکر می‌کرد سرور کند شده، اما مصرف CPU و RAM طبیعی بود.

علائم:

  • خطای «Query execution was interrupted» فقط در گزارش‌های ماهانه
  • هیچ خطای دیگری در لاگ نبود
  • ساعت‌های گزارش معمولاً صبح‌ها بود، بدون همزمانی با پیک ترافیک

تشخیص:

با اجرای SHOW VARIABLES LIKE 'max_execution_time'، مقدار 25000 (۲۵ ثانیه) را دیدم. این پارامتر توسط پنل مدیریت هاست به‌طور پنهان تنظیم شده بود. سپس با اجرای گزارش به‌صورت دستی در phpMyAdmin، دیدم که کوئری گزارش دقیقاً حدود ۲۸ ثانیه طول می‌کشد و به همین دلیل قطع می‌شود.

درمان:

  1. ابتدا با تحلیل EXPLAIN، کوئری را بررسی کردم و متوجه شدم که یک JOIN بدون ایندکس روی wp_postmeta اجرا می‌شود.
  2. یک ایندکس ترکیبی روی ستون‌های کلیدی اضافه کردم.
  3. زمان اجرای گزارش از ۲۸ ثانیه به ۳.۵ ثانیه کاهش یافت.

درس‌آموخته:

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

حرف آخر: زمان‌بندی، نه تخریب

خطای «Query execution was interrupted» در نگاه اول ترسناک است، اما در واقع یک ابزار محافظتی در دست ادمین است تا یک کوئری سرکش، منایع سرور را نبلعد. اگر این خطا را می‌بینید، احتمالاً کوئری شما به سقف زمانی نزدیک شده است. سؤال درست این نیست «چطور سقف را بالاتر ببرم»، بلکه این است «چرا کوئری من این‌قدر طول می‌کشد».

از تجربه‌ام، چهار اصل عملی بیشترین بازدهی را داشته‌اند: اول، لاگ کندی کوئری را فعال کنید تا قبل از قطع شدن، کوئری‌های مشکوک را بشناسید. دوم، ایندکس‌گذاری اصولی روی ستون‌های فیلتر را جدی بگیرید. سوم، گزارش‌های سنگین را به‌جای اجرای مستقیم، کش کنید. چهارم، از تراکنش‌ها به‌درستی استفاده کنید تا قطع کوئری به نیمه‌کاره ماندن داده منجر نشود.

در نهایت، اگر روی هاست اشتراکی هستید، باید بپذیرید که یک سقف زمانی اجباری وجود دارد که نمی‌توانید آن را تغییر دهید. در این حالت، تنها راه‌حل واقعی، بهینه‌سازی کوئری یا مهاجرت به هاست حرفه‌ای‌تر است. اگر هم خودتان سرور اختصاصی دارید، باید بین دو گزینه تصمیم بگیرید: افزایش سقف زمانی (با ریسک مصرف منابع) یا بهینه‌سازی کوئری (با ریسک زمان توسعه). در ۹۰٪ پروژه‌هایی که دیده‌ام، گزینه دوم جواب داده است.

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