تقریباً هر کسی که با PHP سروکار داشته باشد یک بار با خطای Maximum execution time exceeded روبهرو شده. معمولاً هم وسط یک کار مهم پیش میآید. مثلا وقتی دارید داده سنگین پردازش میکنید و ناگهان اسکریپت قطع میشود. دلیلش هم خیلی ساده است. PHP برای هر اسکریپت یک زمان اجرای محدود میگذارد تا سرور بیش از حد درگیر نشود. اما همیشه هم این محدودیت منطقی نیست. مخصوصاً وقتی کار، زمانبر است. برای همین لازم است چند روش عملی برای افزایش max_execution_time را بلد باشید تا همیشه وسط کار غافلگیر نشوید.
max_execution_time چیست؟
به طور ساده PHP میگوید این اسکریپت فقط تا یک مدت مشخص حق دارد اجرا شود. اگر از آن زمان عبور کند متوقفش میکنم. مقدار پیشفرض در بیشتر سرورها 30 ثانیه است. نکتهای که خیلیها اشتباه میفهمند این است که این زمان فقط مربوط به پردازش CPU است. یعنی اگر اسکریپت منتظر دانلود یک فایل باشد یا منتظر پاسخ سرور دیگر بماند این زمان شمرده نمیشود. همین نکته باعث میشود گاهی فکر کنیم مشکل از کم بودن زمان اجراست در حالی که مشکل از جای دیگری است.
چرا Timeout اتفاق میافتد؟
گاهی دلیل کاملاً مشخص است. مثلا داده بزرگ یا حلقه طولانی. اما همیشه هم دلیل همین نیست.
پردازشهای سنگین
اگر با تصویر، ویدیو، گزارشهای حجیم یا خروجی گرفتن از دیتابیس سروکار دارید احتمال Timeout بالاست.
کوئری های کند
گاهی مشکل از PHP نیست. از دیتابیس است. یک کوئری اشتباه ممکن است چندین ثانیه وقت CPU را بگیرد.
فایل های بزرگ
خواندن فایل حجیم روی هارد کند است و اسکریپت را عقب میاندازد.
حلقههای غیرضروری
گاهی تنها با حذف یک حلقه اضافی مشکل کاملاً حل میشود.
روشهای افزایش max_execution_time
استفاده از ini_set
اگر فقط برای یک فایل خاص مشکل دارید سادهترین روش این است:
ini_set('max_execution_time' 300)
این روش سریع است و فقط روی همان فایل اثر میگذارد. البته روی بعضی هاستها محدود میشود.
ویرایش php.ini
اگر دسترسی دارید بهترین کار تغییر مستقیم مقدار در php.ini است. چون روی تمام اسکریپتها اعمال میشود.
max_execution_time = 300
بعد از ذخیره باید سرویس PHP را ریستارت کنید تا مقدار جدید فعال شود.
استفاده از set_time_limit
گاهی اسکریپت شما مرحلهبهمرحله اجرا میشود. در این شرایط set_time_limit کمک بزرگی است.
set_time_limit(300)
زمان را از صفر شروع میکند. یعنی اگر اسکریپت ۱۰ ثانیه گذشته باشد این تابع دوباره وقت جدید میدهد.
افزایش از طریق htaccess
اگر Apache دارید و اجازه تغییرات فعال است این روش هم جواب میدهد.
php_value max_execution_time 300
البته روی سرورهایی که PHP-FPM دارند بیاثر میشود.
کنترل پنلهای هاست
در cPanel DirectAdmin یا Plesk معمولاً بخشی برای تنظیم max_execution_time وجود دارد . نیازی به کدنویسی هم نیست .
روشهای جلوگیری از Timeout
تقسیم پردازش سنگین
تا جایی که میشود پردازش را بخشبندی کنید. مثلا پردازش ۲۰ هزار رکورد را به ۵ بخش ۴ هزار تایی تبدیل کنید.
استفاده از صف
برای کارهای طولانی مثل ایمپورت داده سنگین یا تبدیل ویدیو بهتر است از Queue استفاده کنید. مثلا با Supervisor یا Redis.
Cronjob
گاهی نیازی نیست کار همان لحظه انجام شود. اگر اینطور است Cronjob بهترین انتخاب است.
بهینهسازی دیتابیس
یک Index درست گاهی بیشتر از ۳۰۰ ثانیه افزایش زمان اجرا ارزش دارد.
مقدار صفر نگذارید
برخی افراد مقدار را صفر میگذارند تا محدودیت برداشته شود اما این کار در پروژه واقعی منطقی نیست چون اگر اسکریپت گیر کند سرور را مصرف میکند.
نتیجهگیری
در نهایت افزایش max_execution_time همیشه راهحل اصلی نیست. اگر کد ساختار خوبی نداشته باشد تنها زمان اجرا را بیشتر میکنید و فقط مشکل را عقب میاندازید. بهترین حالت این است که قبل از افزایش مقدار مشکلات داخل اسکریپت بررسی شود. اگر حلقههای طولانی دارید بهتر است آنها را سبکتر کنید. کوئری کند دارید اصلاحش کنید. اگر کار سنگین است آن را به صف منتقل کنید. افزایش زمان اجرا تنها زمانی ارزش دارد که کار واقعاً زمانبر باشد و ساختار کد درست باشد. اینطوری هم سرور تحت فشار قرار نمیگیرد و هم اسکریپت بدون توقف اجرا میشود.