当前位置: 首页 > 知识库问答 >
问题:

Laravel/Elount内存泄漏重复检索同一记录

牧献
2023-03-14

我正在尝试编写一个laravel函数,它从一个数据库中获取大量记录(100000条),然后将其放入另一个数据库中。为此,我需要查询我的数据库,看看这个用户是否已经存在。我反复称此代码:

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

然后在这种情况发生几百次后,我运行内存溢出。所以,我做了一个使用所有可用内存的极简主义例子,它看起来像这样:

<?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'执行)如下所示:

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

如果我注释掉一行"$user=User::其中('id', '=', 2)-

有人知道为什么这一行会像这样使用内存,或者知道一种更聪明的方法来完成我想做的事情吗?

谢谢你的时间。

共有2个答案

崔涵亮
2023-03-14

我不能说为什么它没有释放记忆。你最好的选择是遵循代码,学习它是如何做到这一点的。或者问泰勒。

至于你可以做的其他事情:

缓存查询如果一遍又一遍地调用相同的查询,请使用查询缓存。这就像添加一样简单-

让DBMS完成所有的艰苦工作。理想情况下,您只需在select语句中插入一个,但当您跨越数据库时,这会变得很棘手。作为替代,批处理select和insert查询,这样可以减少对数据库的调用,并创建更少的对象。这将把更多的繁重工作转移到数据库管理系统上,而数据库管理系统在这些类型的任务中可能更高效。

柯苗宣
2023-03-14

我重新创建了您的脚本,并使用调试器进行了调试,因为我不知道什么样的可怕事情会导致这种类型的内存问题。当我走过时,我遇到了这样一个问题:

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

在Laravel中运行的每个查询似乎都存储在持久日志中,这解释了每次查询后内存使用量增加的原因。就在上面,是下面的一行:

if ( ! $this->loggingQueries) return;

再深入一点,就确定loggingQuery属性默认设置为true,并且可以通过disableQueryLog方法进行更改,因此这意味着,如果您调用:

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

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

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

重新开始伐木。

 类似资料:
  • 或者javascript引擎足够聪明,不会在内存中保存函数的词法环境的值,而它不使用这个环境?

  • 问题内容: 是否有一些工具可以检测Node.js中的内存泄漏?并告诉我您在测试nodejs应用程序方面的经验。 问题答案: 以下工具对于发现内存泄漏很有用: 节点检查器 还有一个教程可以帮助您在此处查找内存泄漏: https://github.com/felixge/node-memory-leak- tutorial

  • 我在哪里可以找到libc_malloc_debug_leak。还有libc_malloc_debug_qemu。那么对于不同的Android版本(冰淇淋三明治、果冻豆、KitKat)和不同的设备(Galaxy Nexus、Nexus 7、Nexus 10)呢?

  • 问题内容: 我认为我的android应用正在泄漏内存。我不是绝对确定这是问题所在。 应用程序打开时经常崩溃,并且logcat尝试加载位图图像时会显示“内存不足”异常。 崩溃后,我重新打开了该应用程序,它运行正常。Logcat会显示许多“ gc”,并且JIT表会不时地向上调整大小,而不会向下调整,直到应用程序因内存不足错误而崩溃。 这听起来像是内存泄漏吗?如果是这样,我该如何定位和关闭泄漏点。 这是

  • 问题内容: 我一直在追寻内存泄漏(由“ valgrind –leak-check = yes”报告),它似乎来自ALSA。这段代码已经存在于自由世界中一段时间​​了,所以我猜这是我做错的事情。 输出看起来像这样: 并继续一些页面 这是由于我在一个项目中使用ALSA并开始看到这种巨大的泄漏……或者至少是所说泄漏的报告。 所以问题是:是我,ALSA或valgrind在这里遇到问题吗? 问题答案: ht