本质是PHP运行环境、框架配置、数据库交互和业务逻辑在Linux上叠加暴露资源瓶颈,解决关键在于切断内存堆积路径:关调试与日志、调优PHP-FPM、改分页为游标或生成器、Session/缓存切Redis、非实时操作入队列。

Linux部署ThinkPHP时出现内存溢出,本质不是“Linux的问题”,而是PHP运行环境、框架配置、数据库交互和业务逻辑在Linux服务器上叠加暴露了资源瓶颈。解决关键不在加内存,而在切断内存持续堆积的路径。
关掉调试和日志,省下30%以上峰值内存
ThinkPHP默认开启调试时,会全程记录SQL、堆栈、模板编译缓存,这些数据全驻留在PHP内存里不释放。上线必须确保:
-
app_debug = false(config/app.php) -
log.level = 'error'或直接禁用日志驱动 - 删除
runtime/log/下所有历史日志文件(避免启动扫描) - CLI命令如队列消费可单独调高内存:
php -d "memory_limit=512M" think queue:work
PHP-FPM不能只拉max_children,要控单worker内存
万级并发下,每个PHP-FPM worker若占40MB,64个就吃掉2.5GB——但服务器可能只有4GB总内存。必须双管齐下:
- 设
pm = static或dynamic,4核8G机器推荐:pm.max_children = 64pm.start_servers = 32pm.min_spare_servers = 16pm.max_spare_servers = 48 - 同步压单worker内存:关debug、禁trace、不用dump、避免大数组全局缓存
数据库查询别碰offset分页,换游标或生成器paginate()查百万数据时,MySQL先扫前N行再取结果,PHP还要把整页数据load进数组——内存爆是必然。应改用:
- 游标分页(按id):
Db::name('order')->where('id', '>', $lastId)->limit(500)->select() - 生成器封装:每次只拉一页,处理完自动释放变量
- 导出类场景用
Db::cursor():返回PDOStatement,fetch()逐行读,内存恒定几百KB
Session和缓存必须切Redis,别用file驱动
file Session和file Cache在高并发下会产生文件锁竞争,所有请求排队等同一个文件,既拖慢响应又卡住worker释放内存。务必:
- Session驱动设为redis:
'type' => 'redis', 'use_trans_id' => true - 缓存统一走redis:
Cache::store('redis')->get('key'),避免Cache::get()走默认file - Redis key带业务前缀和TTL(如
user:info:123:202608,TTL≤3600)
非实时操作全部丢进队列,HTTP链路只做调度
登录记录、消息推送、统计更新这类操作,同步执行会让一个慢请求拖住整个worker。应:
- 控制器里只发任务ID:
Queue::push(new SendNotifyJob($userId)) - 队列消费用独立进程:
php think queue:work --daemon - CLI模式下单独设内存上限,不与Web请求争资源
不复杂但容易忽略



















