ข้ามไปยังเนื้อหา
การตั้งค่า

แก้ปัญหา "Allowed Memory Size Exhausted" ใน WordPress

ถ้าเว็บของคุณขึ้น Fatal error: Allowed memory size of 268435456 bytes exhausted ให้เพิ่มบรรทัดนี้ลงใน wp-config.php เหนือบรรทัด / That's all, stop editing! /

เผยแพร่แล้ว

ถ้าเว็บของคุณขึ้น Fatal error: Allowed memory size of 268435456 bytes exhausted ให้เพิ่มบรรทัดนี้ลงใน wp-config.php เหนือคอมเมนต์ /* That's all, stop editing! */: define( 'WP_MEMORY_LIMIT', '256M' ); วิธีนี้ทำให้เว็บส่วนใหญ่กลับมาออนไลน์ได้ภายในไม่ถึงนาที แต่ก่อนจะเดินจากไป อ่านส่วนที่เหลือของหน้านี้ให้จบก่อน เพราะการเพิ่มลิมิตคือการวินิจฉัย ไม่ใช่การรักษา ถ้าเว็บพังอีกครั้งที่ตัวเลขสูงขึ้น แสดงว่าปัญหาจริงคือโค้ดที่กินหน่วยความจำแบบไม่มีขอบเขต และการยกเพดานให้สูงขึ้นก็แค่ยืดเชือกให้มันยาวขึ้นเท่านั้น

error นี้หมายความว่าอะไรจริง ๆ

PHP จะติดตามว่าแต่ละ request จองหน่วยความจำไปเท่าไหร่ เมื่อ request เดียวพยายามจองเกิน memory_limit ที่ตั้งไว้ใน php.ini (หรือถูกแทนที่โดย WordPress) PHP จะหยุด request นั้นทันทีด้วย fatal error พร้อมพิมพ์จำนวนไบต์ที่มันตายออกมา 268435456 bytes คือ 256M 134217728 คือ 128M 536870912 คือ 512M ตัวเลขหลังคำว่า “tried to allocate” บอกขนาดของฟางเส้นสุดท้าย ไม่ใช่ขนาดของปัญหา

WordPress ยังซ้อนลิมิตของตัวเองทับ PHP อีกชั้น WP_MEMORY_LIMIT (ค่าเริ่มต้น 40M หรือเท่ากับลิมิตของ PHP ถ้าสูงกว่า) ควบคุมฝั่งหน้าเว็บ ส่วน WP_MAX_MEMORY_LIMIT (ค่าเริ่มต้น 256M) ควบคุมงานฝั่งแอดมิน เช่น media library และการอัปเดต ปลั๊กอิน wordpress ซึ่งจำเป็นต้องใช้มากกว่าจริง ๆ WordPress จะเรียก ini_set('memory_limit', ...) ตอนโหลดตามค่าคงที่เหล่านี้ แต่จะได้ผลก็ต่อเมื่อโฮสต์ของคุณอนุญาต ini_set และได้เพียงไม่เกินเพดานสูงสุดที่โฮสต์ตั้งไว้เท่านั้น ส่วนสุดท้ายนี่แหละคือเหตุผลที่การแก้ wp-config.php บางครั้งดูเหมือนไม่มีผลอะไรเลย

แก้ทีละขั้น ตามลำดับ

1. เพิ่มลิมิตของ WordPress ใน wp-config.php นี่คือสิ่งแรกที่ควรลอง เพราะย้อนกลับได้และไม่ไปแตะอะไรอย่างอื่น

define( 'WP_MEMORY_LIMIT', '256M' );
define( 'WP_MAX_MEMORY_LIMIT', '512M' );

ถ้าคุณไม่แน่ใจว่าบรรทัดพวกนี้ต้องวางตรงไหน หรืออยากตั้งค่าคงที่ตัวอื่น ๆ ที่ใช้บ่อยให้ถูกต้องไปพร้อมกัน wp-config generator ของเราจะสร้างบล็อกที่สะอาดให้คุณคัดลอกไปวางได้เลย ตำแหน่งการวางสำคัญมาก อะไรก็ตามที่อยู่ใต้บรรทัด “stop editing” จะถูกละเว้นทั้งหมด

2. ถ้าทำแล้วไม่มีอะไรเปลี่ยน แสดงว่าโฮสต์กำลังจำกัด PHP อยู่ ให้เพิ่ม memory_limit ที่ระดับ PHP โดยตรง ใน php.ini:

memory_limit = 256M

บนโฮสต์แบบ shared หลายเจ้า คุณไม่สามารถแก้ php.ini ได้โดยตรง ให้ลองใช้ไฟล์ .user.ini ใน web root แทน หรือตั้งค่าผ่าน .htaccess บนระบบ Apache/mod_php:

php_value memory_limit 256M

ข้อควรระวัง php_value ใน .htaccess จะทำให้เกิด error 500 บน nginx หรือระบบ PHP-FPM เพราะมันเป็นคำสั่งเฉพาะของ Apache/mod_php ถ้าคุณเจอ error 500 หลังเพิ่มบรรทัดนี้ นั่นแหละคือสาเหตุ ให้ลบออกแล้วใช้ .user.ini แทน

3. ยืนยันค่าที่ใช้งานอยู่จริง อย่าเชื่อสิ่งที่คุณแก้ ให้เชื่อสิ่งที่ PHP รายงาน วางไฟล์บรรทัดเดียวไว้ที่ web root:

<?php echo ini_get('memory_limit');

เปิดในเบราว์เซอร์ อ่านค่า แล้วลบไฟล์ทิ้ง ถ้ามันยังขึ้น 128M ทั้งที่คุณตั้ง 256M ไปแล้ว แสดงว่าโฮสต์กำลังแทนที่ค่าของคุณอยู่ คุณต้องติดต่อโฮสต์หรือใช้การตั้งค่าในแผงควบคุมของเขา

ส่วนที่คู่มือส่วนใหญ่มักข้ามไป

การเพิ่มลิมิตคือการวินิจฉัย นี่คือวิธีอ่านผลลัพธ์

ถ้าคุณตั้ง 256M แล้วเว็บอยู่ได้ปกติภายใต้ทราฟฟิกทั่วไป แสดงว่าเพดานเดิมของคุณต่ำเกินไปจริง ๆ พบบ่อยในเว็บที่มี media library ขนาดใหญ่ WooCommerce หรือ page builder เท่านี้ก็จบ

ถ้าคุณตั้ง 256M แล้วมันพังอีก แล้วตั้ง 512M แล้วก็พังอีก หยุดเพิ่มได้แล้ว request ของ WordPress ปกติไม่ต้องใช้ถึง 512M เมื่อการใช้หน่วยความจำไต่ขึ้นเรื่อย ๆ โดยไม่มีเพดาน แสดงว่ามีบางอย่างวนลูปหรือสะสมอยู่ เช่น ปลั๊กอินที่โหลดทั้งตารางฐานข้อมูลเข้ามาในอาร์เรย์ หรือ add_action ที่เรียกตัวเองซ้ำแบบวนซ้ำ หรือ routine การนำเข้าที่เก็บทุกแถวไว้ในหน่วยความจำพร้อมกัน หรือปลั๊กอินสองตัวชนกันภายใน hook เดียวกัน การเพิ่มลิมิตไม่ได้แก้ลูปที่ไม่มีขอบเขต มันแค่เลื่อนจุดพังออกไปไม่กี่วินาที และทำให้ทำซ้ำเพื่อหาสาเหตุได้ยากขึ้น

การจะหาต้นตอ ให้ปิดการใช้งานปลั๊กอินทั้งหมดแล้วสลับไปใช้ธีมเริ่มต้น เช่น Twenty Twenty-Four ถ้า error หายไป ให้เปิดใช้งานทีละตัวจนกว่ามันจะกลับมา เปิด debug log เพื่อจับว่ามันตายตรงไหน:

define( 'WP_DEBUG', true );
define( 'WP_DEBUG_LOG', true );
define( 'WP_DEBUG_DISPLAY', false );

บรรทัด fatal ใน wp-content/debug.log จะบอกชื่อไฟล์และหมายเลขบรรทัดที่จองก้อนสุดท้าย ซึ่งมักจะเป็นตัวลูปเอง หรืออยู่ห่างจากมันแค่การเรียกฟังก์ชันเดียว

สิ่งที่ไม่ควรทำ

อย่าตั้ง WP_MEMORY_LIMIT เป็น -1 หรือ 1024M แล้วปล่อยลืมไป หน่วยความจำไม่จำกัดไม่ได้แก้การรั่ว มันแค่ปล่อยให้ request ที่หลุดคุมกินทั้งเซิร์ฟเวอร์ ซึ่งอาจทำให้เว็บอื่น ๆ ทุกเว็บบนเครื่องเดียวกันล่มไปด้วย และทำให้คุณได้รับโทรศัพท์จากโฮสต์ เพดานคือฟีเจอร์ความปลอดภัย เก็บมันไว้

อย่าวาง ini_set('memory_limit', '512M') ลงใน functions.php เป็นวิธีแก้หลัก มันทำงานช้าเกินไปสำหรับความล้มเหลวบางกรณี ถ้าเว็บพังระหว่างการโหลด core ของ WordPress ก่อนที่ functions.php ของธีมจะทำงาน บรรทัดนั้นจะไม่มีวันถูกรัน wp-config.php โหลดก่อนหน้า และเป็นที่ที่ถูกต้อง

อย่าเหมาว่ามันเป็นปัญหาของโฮสต์แล้วอัปเกรดแพ็กเกจ บางครั้งมันเป็นโฮสต์ที่เล็กเกินไปจริง ๆ แต่บ่อยครั้งอาการพังแบบเป๊ะ ๆ เดิมก็ตามคุณไปยังแพ็กเกจใหญ่ขึ้น เพราะต้นตอมันติดไปกับปลั๊กอินของคุณด้วย ตัดปัญหาเรื่องลูปออกไปก่อน มันฟรี

อย่าเพิ่ม memory_limit เพื่อแก้ error ของ max_execution_time มันเป็นลิมิตคนละตัวที่มีข้อความคนละแบบ หน่วยความจำหมดจะขึ้นว่า “Allowed memory size … exhausted” ส่วน timeout จะขึ้นว่า “Maximum execution time … exceeded” การเพิ่มผิดตัวจะเสียเวลาไปทั้งบ่าย

ยังติดอยู่ใช่ไหม

ถ้าคุณยืนยันแล้วว่าลิมิตที่ใช้งานจริงคือ 256M หรือสูงกว่านั้น ทดสอบด้วยการปิดปลั๊กอินทั้งหมดและใช้ธีมเริ่มต้นแล้ว แต่มันยังใช้หน่วยความจำหมดอยู่ แสดงว่าคุณมีการรั่วจริงที่ควรตามล่าใน debug log มากกว่าเป็นเพดานที่ควรยกให้สูงขึ้น จับบรรทัด fatal เอาไว้ ดูว่ามันชี้ไปยังโฟลเดอร์ของปลั๊กอินตัวไหน นั่นแหละคือรายงานบั๊กของคุณ ตั้งค่าคงที่พื้นฐานใน wp-config.php ให้ถูกต้องก่อนด้วย wp-config generator เพื่อให้แน่ใจว่าลิมิตถูกตั้งไว้ตรงที่คุณคิด แล้วค่อยไปอ่าน log