خطأ استنفاد ذاكرة PHP 128 ميجابايت: الأسباب والحلول

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

«Allowed Memory Size of 134217728 Bytes Exhausted» — كابح طوارئ تطبيق PHP الخاص بك

\n\n

هل سبق لك أن رأيت هذه الرسالة في منتصف الليل، عندما يتعطل موقعك فجأة، وتظهر في السجلات كتابة بيضاء على خلفية سوداء؟ إذا كان الأمر كذلك، فأنت لست وحدك. آلاف المطورين على Stack Overflow تساءلوا لماذا يستهلك سكربت PHP الذي يبدو غير ضار فجأة كل 128 ميجابايت من ذاكرة الوصول العشوائي ويتعطل مع خطأ فادح.

\n\n

دعنا نفهم ما يعنيه هذا الخطأ حقًا، ولماذا يحدث، والأهم من ذلك، كيفية إصلاحه نهائيًا. لن نقوم فقط بزيادة حد الذاكرة — بل سنتعلم كتابة كود لا يستهلك الموارد مثل طالب جائع في الكافتيريا.

\n\n

ماذا يعني «134217728 Bytes Exhausted»؟

\n\n

الرقم 134,217,728 هو 128 ميجابايت. هذا هو مقدار الذاكرة المسموح لسكربت PHP باستخدامه افتراضيًا. عندما يحاول السكربت تخصيص المزيد — بام! — وستحصل على Fatal Error. هذه آلية حماية تمنع سكربتًا واحدًا من تعطيل الخادم بأكمله.

\n\n

ولكن المشكلة هي: 128 ميجابايت قليلة جدًا للتطبيقات الحديثة. معالجة ملف XML كبير، إنشاء تقرير من قاعدة بيانات، العمل مع الصور أو المكتبات الثقيلة — كل هذا يمكن أن يتجاوز الحد بسهولة.

\n\n

لماذا يحدث هذا؟ ثلاثة أسباب رئيسية

\n\n
    \n
  • الحلقات الجشعة والتكرار — عندما تقوم بتحميل جميع البيانات إلى الذاكرة دفعة واحدة، بدلاً من معالجتها على أجزاء.
  • \n
  • تسرب الذاكرة — المتغيرات الثابتة، المصفوفات العامة، والاستخدام الخاطئ لـ static يمكن أن تتراكم البيانات.
  • \n
  • المكتبات والإضافات الثقيلة — مثل معالجة الصور عبر GD أو العمل مع PDF.
  • \n
\n\n

كيفية إصلاح الخطأ: من البسيط إلى المعقد

\n\n

الطريقة 1: زيادة حد الذاكرة (حل سريع)

\n\n

الطريقة الأكثر وضوحًا هي ببساطة إعطاء PHP ذاكرة أكبر. لكن تذكر: هذا ليس علاجًا، بل مسكن ألم. إذا كان كودك سيئًا، فسيستهلك 512 ميجابايت و1 جيجابايت أيضًا.

\n\n

هناك ثلاث طرق لزيادة الحد:

\n\n

1. في ملف php.ini (تغيير دائم):

\n
memory_limit = 256M
\n\n

2. في .htaccess (إذا كان متاحًا):

\n
php_value memory_limit 256M
\n\n

3. داخل السكربت نفسه (للتشغيل الحالي فقط):

\n
ini_set('memory_limit', '256M');
\n\n

لكن تحذير: إذا كنت على استضافة مشتركة، قد لا يسمح لك المضيف بزيادة الحد فوق عتبة معينة. وحتى لو سمح — لا تسيء الاستخدام.

\n\n

الطريقة 2: تحسين الكود — الحل الحقيقي

\n\n

بدلاً من إعطاء السكربت ذاكرة أكبر، دعنا نعلمه استخدام ما هو متاح بذكاء.

\n\n

استخدم unset() لتحرير الذاكرة

\n\n

PHP ليست C++، لكن إدارة الذاكرة اليدوية لا تزال تعمل. عندما لا تحتاج إلى متغير كبير بعد الآن — احذفه:

\n\n
$data = file_get_contents('huge_file.csv');\n// معالجة البيانات\nprocessData($data);\n// تحرير الذاكرة\nunset($data);\n
\n\n

عالج البيانات على أجزاء

\n\n

بدلاً من تحميل 100,000 سطر من قاعدة البيانات إلى الذاكرة، استخدم المؤشرات أو الحدود:

\n\n
// سيء: تحميل كل شيء في الذاكرة\n$users = $db->query("SELECT * FROM users")->fetchAll();\n\n// جيد: معالجة سطر بسطر\n$stmt = $db->query("SELECT * FROM users");\nwhile ($row = $stmt->fetch()) {\n    processUser($row);\n    // PHP سيحرر الذاكرة تلقائيًا بعد كل تكرار\n}\n
\n\n

استخدم المولدات (yield)

\n\n

المولدات هي سحر للعمل مع مجموعات البيانات الكبيرة. لا تخزن جميع القيم في الذاكرة:

\n\n
function getLargeData() {\n    for ($i = 0; $i < 1000000; $i++) {\n        yield $i;\n    }\n}\n\nforeach (getLargeData() as $value) {\n    // معالجة عنصر واحد في كل مرة\n    echo $value . "\\n";\n}\n

المدونات

توصيات الكتب