先确认是否真内存不足,再决定是否调整memory_limit;用memory_get_usage(true)和memory_get_peak_usage(true)在fetchAll()、json_decode()等关键位置打点,结合错误日志行号定位真实泄漏源,避免盲目调大掩盖问题。

别急着改 memory_limit,先确认是不是真缺内存——PHP 8.3 报 “Allowed memory size exhausted”,90% 的 case 是代码吃相难看,不是配置太小。
怎么判断是真内存不足,还是脚本在偷偷吃内存
错误日志里那行“exhausted”只告诉你撞墙了,不告诉你谁推的墙。得靠打点实测:
-
memory_get_usage(true)比默认参数更准,返回当前实际分配字节数(含未释放碎片) -
memory_get_peak_usage(true)查峰值,再和ini_get('memory_limit')对比,才能知道是不是真快到上限 - 重点插点位置:
PDOStatement::fetchAll()前后、json_decode()大字符串前后、循环体内外 - 常见真凶:
$stmt->closeCursor()忘调、递归没出口、闭包意外持有了大数组或资源句柄
四种改法,生效条件和静默失效点完全不同
不是所有方式在所有环境都管用,搞错就白改:
-
脚本内用
ini_set('memory_limit', '512M'):必须写在<?php后第一行,早于任何大变量初始化;若已被disable_functions禁掉,这行完全不生效(也不报错) -
CLI 命令行临时覆盖:
php -d memory_limit=1G script.php—— 最安全,绕过所有权限限制,不影响 Web 服务 -
改
php.ini:先用php --ini或phpinfo()确认 CLI 和 FPM 加载的是哪个文件(常不同);改完必须systemctl restart php-fpm或apache2,reload不生效 -
.htaccess(仅 Apache + mod_php):php_value memory_limit 384M,单位必须大写M,且服务器需开启AllowOverride Options,否则直接 500
生产环境推荐值和配套动作
设太大不解决问题,反而掩盖泄漏、拖慢定位:
立即学习“PHP免费学习笔记(深入)”;
- 中小项目常规接口:设
256M;含图像处理、Excel 导出、大 JSON 解析的场景,可设512M - 绝对不要设
-1(无限制),OOM 会直接 kill 进程,日志都来不及写 - 同步调高
max_execution_time=120和max_input_time=60,尤其对接外部 API 或批量导入时 - 配合
pm.max_requests=500(PHP-FPM),防长期运行导致内存缓慢泄漏
真正难的不是改数字,而是区分“脚本撑爆内存”和“内存被悄悄锁住不放”。比如一个 foreach 里不断 $data[] = $row 却没 unset,或者 PDO 结果集没 closeCursor,这些地方改再大的 memory_limit 都只是延缓爆炸时间。



















