memory_limit 是 php 运行时限制而非 laravel 配置,需分别检查 php.ini、php-fpm 的 www.conf(php_admin_value[memory_limit])和 cli 的 php.ini;eloquent 大量加载、with+get 组合、未禁用事件等易致内存暴涨,应改用 chunk()、withoutevents()、gc_collect_cycles() 等优化。

memory_limit 不是 Laravel 自己的配置项,而是 PHP 的运行时限制。Laravel 本身不设内存上限,它完全受制于 PHP 解析器的 memory_limit 设置。改错地方、改漏位置、重启不全,都会导致你以为改了但实际没生效。
直接改 php.ini 的 memory_limit 行不通?检查这三处
CentOS 上常见情况是:你改了 /etc/php.ini,却忘了 PHP-FPM 或 CLI 环境各自有独立配置。
- Web 请求走的是 PHP-FPM,需确认
php-fpm.d/www.conf中是否覆盖了该值:php_admin_value[memory_limit] = 512M—— 这个设置会强制覆盖php.ini中的值 - Artisan 命令(如
php artisan queue:work)走的是 CLI 模式,对应的是/etc/php.d/cli/php.ini或/etc/php-cli.ini,不是 Web 那个php.ini - 用
php --ini和php -r "echo ini_get('memory_limit');"分别在 CLI 和 Web 环境下验证,别只信一个结果
为什么改了 memory_limit 还爆内存?重点看 Eloquent 处理方式
Laravel 内存暴涨最常发生在一次性加载大量模型上,比如 Model::get() 返回几千条记录,每条都带关系、访问器、事件监听器 —— 这比单纯 PHP 内存限制更致命。
- 用
chunk()替代get():避免把全部数据塞进内存,Model::chunk(200, function ($models) { ... }) - 禁用模型事件:临时关闭观察者和事件分发,
Model::withoutEvents(function () { ... }) - 查完立刻释放:处理完一批后手动调用
gc_collect_cycles(),尤其在长周期队列任务里 - 警惕
with()+get()组合:预加载 N+1 关系时,若关联表也很大,内存会指数级增长;改用延迟加载或 ID 映射替代
OPcache 和 Laravel 缓存驱动对内存的实际影响
很多人以为开 OPcache 就能省内存,其实它主要省 CPU 和重复编译开销;而 Laravel 的缓存驱动选错,反而会吃更多内存。
-
CACHE_DRIVER=file和SESSION_DRIVER=file是 CentOS 低配机的稳妥选择,避免 Redis/Memcached 客户端额外驻留内存 - OPcache 的
opcache.memory_consumption要设够(建议 ≥128),否则频繁重编译 .php 文件反而触发更多内存分配 -
config:cache和route:cache必须做 —— 未缓存的配置/路由每次请求都要解析 PHP 数组,累积起来很可观 - 不要在
.env里写MEMOIZE_DRIVER=file(这是错的键名),正确是CACHE_DRIVER=file
swap 不是解药,而是兜底信号
加 /swapfile 只会让 OOM Killer 杀进程的时间晚一点,不会解决根本问题。一旦看到 swapon --show 显示 swap 使用率 >30%,说明 PHP 已经在反复换页,响应延迟会明显升高。
- swap 启用后必须监控:
free -h看Swap行,vmstat 1看si/so列(非零即在频繁换入换出) - swap 是磁盘 IO,不是内存 —— 它缓解的是“立即死”,不是“跑得慢”
- 真正要盯的是
top里 PHP 进程的 RES(物理内存占用),如果单个php-fpm进程长期 >300MB,就得回代码层排查了
memory_limit 是最快见效的手段,但也是最容易掩盖真实问题的操作。真正难的,是判断哪段 Eloquent 查询在 quietly 吃掉 400MB —— 那些没报错、只变慢、日志里也看不出异常的部分,才是内存优化中最容易被跳过的点。











