You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel项目每20分钟触发内存耗尽错误排查求助

Laravel 5.8 内存耗尽问题排查方案

是否与Laravel相关?

报错位置在Doctrine DBAL(Laravel默认依赖的数据库操作组件),但仅有的#0 {main}栈追踪无法直接确认是Laravel核心问题。大概率是某类请求/后台操作触发的数据库逻辑导致内存泄漏,比如:

  • 未正确处理的大结果集查询(未分页、未使用chunk)
  • 循环内重复执行查询且未释放资源
  • 自定义代码/第三方扩展中的内存泄漏,通过数据库组件触发

日志优化代码方案

以下代码可帮你捕获更多错误上下文,无需修改php.ini:

1. 监控PDO语句执行细节

在AppServiceProvider的boot方法中添加代码,拦截PDO执行过程并记录关键信息:

use Doctrine\DBAL\Driver\PDOStatement;
use Illuminate\Support\Facades\Log;

public function boot()
{
    \Closure::bind(function() {
        $originalExecute = $this->execute;
        $this->execute = function($params = null) use ($originalExecute) {
            // 记录调用栈、SQL、当前内存
            $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 10);
            Log::warning('PDO Statement Executed', [
                'sql' => $this->queryString,
                'params' => $params,
                'call_stack' => $backtrace,
                'current_memory' => round(memory_get_usage(true)/1024/1024, 2) . 'MB'
            ]);
            
            try {
                return $originalExecute->call($this, $params);
            } catch (\Throwable $e) {
                // 出错时记录峰值内存
                Log::error('PDO Statement Failed', [
                    'sql' => $this->queryString,
                    'params' => $params,
                    'call_stack' => $backtrace,
                    'peak_memory' => round(memory_get_peak_usage(true)/1024/1024, 2) . 'MB',
                    'error' => $e->getMessage()
                ]);
                throw $e;
            }
        };
    }, null, PDOStatement::class)->__invoke();
}

2. 全局请求内存监控

创建app/Http/Middleware/MemoryMonitorMiddleware.php:

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Support\Facades\Log;

class MemoryMonitorMiddleware
{
    public function handle($request, Closure $next)
    {
        $startMem = memory_get_usage(true);
        $response = $next($request);
        
        $usedMem = round((memory_get_usage(true) - $startMem)/1024/1024, 2);
        // 内存占用超过50MB时记录详情
        if ($usedMem > 50) {
            Log::warning('High Memory Request', [
                'method' => $request->method(),
                'uri' => $request->fullUrl(),
                'used_memory' => $usedMem . 'MB',
                'peak_memory' => round(memory_get_peak_usage(true)/1024/1024, 2) . 'MB',
                'client_ip' => $request->ip(),
                'user_agent' => $request->userAgent()
            ]);
        }
        
        return $response;
    }
}

然后在app/Http/Kernel.php的$middleware数组中注册该中间件,监控所有HTTP请求的内存消耗。

3. 增强致命错误日志

修改app/Exceptions/Handler.php的report方法:

public function report(Exception $exception)
{
    if ($this->shouldReport($exception)) {
        // 针对内存耗尽错误补充上下文
        if ($exception instanceof \ErrorException && str_contains($exception->getMessage(), 'Allowed memory size')) {
            Log::critical('Memory Exhausted', [
                'message' => $exception->getMessage(),
                'file' => $exception->getFile(),
                'line' => $exception->getLine(),
                'peak_memory' => round(memory_get_peak_usage(true)/1024/1024, 2) . 'MB',
                'request_uri' => request()->fullUrl() ?? 'CLI/Unknown',
                'request_method' => request()->method() ?? 'CLI',
                'trace' => $exception->getTraceAsString()
            ]);
        }
    }
    
    parent::report($exception);
}

额外排查方向

  • 检查服务器cron任务,确认是否有未配置的定时进程触发请求
  • 查看服务器进程列表,排查是否有持续运行的PHP进程占用内存
  • 核实近期用户行为,是否存在批量数据操作(导入/导出)触发高内存逻辑

内容的提问来源于stack exchange,提问作者Roman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 13:40:24