Laravel/雄辩的内存泄漏重复检索同一条记录 [英] Laravel / Eloquent memory leak retrieving the same record repeatedly

查看:56
本文介绍了Laravel/雄辩的内存泄漏重复检索同一条记录的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试编写一个laravel函数,该函数从一个数据库获取大量记录(100,000多个)并将其放入另一个数据库中.为此,我需要查询数据库并查看用户是否已经存在.我反复调用此代码:

I am trying to write a laravel function that gets lots of records (100,000+) from one database and puts it in another database. Towards that end, I need to query my database and see if the user already exists. I repeatedly call this code:

$users = User::where('id', '=', 2)->first();

然后发生了数百次之后,我的内存不足了.因此,我举了一个使用所有可用内存的极简示例,它看起来像这样:

And then after that happens a few hundred times, I run out of memory. So, I made a minimalist example of it using up all the available memory, and it looks like this:

<?php

use Illuminate\Console\Command;

class memoryleak extends Command
{
    protected $name = 'command:memoryleak';
    protected $description = 'Demonstrates memory leak.';

    public function fire()
    {
        ini_set("memory_limit","12M");

        for ($i = 0; $i < 100000; $i++)
        {
            var_dump(memory_get_usage());
            $this->external_function();
        }
    }

    function external_function()
    {
        // Next line causes memory leak - comment out to compare to normal behavior
        $users = User::where('id', '=', 2)->first();

        unset($users);
        // User goes out of scope at the end of this function
    }
}

此脚本的输出(由"php artisan command:memoryleak"执行)看起来像这样:

And the output of this script (executed by 'php artisan command:memoryleak') looks something like this:

int(9298696)
int(9299816)
int(9300936)
int(9302048)
int(9303224)
int(9304368)
....
int(10927344)
int(10928432)
int(10929560)
int(10930664)
int(10931752)
int(10932832)
int(10933936)
int(10935072)
int(10936184)
int(10937320)
....
int(12181872)
int(12182992)
int(12184080)
int(12185192)
int(12186312)
int(12187424)
PHP Fatal error:  Allowed memory size of 12582912 bytes exhausted (tried to allocate 89 bytes) in /Volumes/Mac OS/www/test/vendor/laravel/framework/src/Illuminate/Database/Connection.php on line 275

如果我将"$ users = User :: where('id','=',2)-> first();"行注释掉,那么内存使用率将保持稳定.

If I comment out the line "$users = User::where('id', '=', 2)->first();" then the memory usage stays stable.

对于这一行为什么会使用这种内存,或者知道一种更聪明的方式来完成我想做的事情,是否有人有任何见识?

Does anyone have any insight as to why this line would use memory like this, or know a smarter way to accomplish what I am trying to do?

谢谢您的时间.

推荐答案

我重新创建了脚本,并使用调试器逐步执行了该脚本,因为我无法理解哪种可怕的事情会导致这种类型的内存问题.当我逐步通过时,我遇到了这个问题:

I recreated your script and stepped through it with a debugger because I couldn't fathom what sort of horrible thing would cause this type of memory issue. As I stepped through, I came across this:

// in Illuminate\Database\Connection
$this->queryLog[] = compact('query', 'bindings', 'time');

似乎您在Laravel中运行的每个查询都存储在一个持久日志中,该日志解释了每次查询后内存使用量的增加.在其上方的是以下行:

It seems every query you run in Laravel is stored in a persistent log, which explains your increasing memory usage after each query. Just above that, is the following line:

if ( ! $this->loggingQueries) return;

再进行一次挖掘即可确定loggingQueries属性默认情况下设置为true,并且可以通过disableQueryLog方法进行更改,这意味着,如果您调用:

A little more digging determined that the loggingQueries property is set to true by default, and can be changed via the disableQueryLog method, so that means, if you call:

 DB::connection()->disableQueryLog();

在执行所有查询之前,您将看不到内存使用量的增加.当我根据您的示例代码运行测试时,它解决了问题.完成后,如果您不想影响应用程序的其余部分,可以致电

before you're going to execute all your queries, you won't see ever increasing memory usage; it solved the problem when I ran my test based on your example code. When you're done, if you don't want to affect the rest of the application you could call

DB::connection()->enableQueryLog();

启用日志记录.

这篇关于Laravel/雄辩的内存泄漏重复检索同一条记录的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆