Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/295.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 为什么;允许的内存大小已耗尽“;?_Php_Memory - Fatal编程技术网

Php 为什么;允许的内存大小已耗尽“;?

Php 为什么;允许的内存大小已耗尽“;?,php,memory,Php,Memory,我正在编写一个批处理脚本,得到一个允许的内存大小为134217728字节的错误 我不明白为什么记忆犹新。我试图取消设置$row变量,但没有改变任何事情。这是我的密码: // ... (sql connection) $result = mysql_query("SELECT * FROM large_table"); while ($row = mysql_fetch_array($result)) { echo $row['id'] . PHP_EOL; unset($row

我正在编写一个批处理脚本,得到一个
允许的内存大小为134217728字节的错误

我不明白为什么记忆犹新。我试图取消设置
$row
变量,但没有改变任何事情。这是我的密码:

// ... (sql connection)
$result = mysql_query("SELECT * FROM large_table");

while ($row = mysql_fetch_array($result)) {
    echo $row['id'] . PHP_EOL;
    unset($row);
}
(简化代码)

为什么记忆会被填满,我怎样才能避免它

注意:这是一个批处理脚本。这是正常的,我必须处理这样的数据(通过100万行)


更新:内存不足发生在第400000行附近,所以这一定是循环中的某个部分?如果可能的话,我希望不必实现分页。

将查询限制为1k个结果,然后再次执行它(当然带有偏移量),直到完成所有表。 您当前的unset没有任何区别,因为$row会被每次while迭代覆盖,所以您可以跳过它

$chunk_size = 1000;
$done = 0;

$keep_asking_for_data = true;
do{
    $result = mysql_query("SELECT * FROM `large_table` LIMIT {$done}, {$chunk_size}");
    $num_rows = mysql_num_rows($result);
    if($num_rows){
        $done += $num_rows;
        while($row = mysql_fetch_assoc($result)){
            echo "{$row['id']}\n";
        }
    } else {
        $keep_asking_for_data = false;
    }
    mysql_free_result($result);
}while($keep_asking_for_data);

在我的头脑中刚刚编译过,希望它能工作=D

如果您使用的是MySQL,请将结果分页,这样您就不会耗尽可用内存。MySQL本身正在占用数据库结果集的内存。请查看以下链接,特别是
选择
限制偏移,限制
语法:


尝试使用(mysql_unbuffered_query())来防止将整个表加载到内存中,但仍然避免分页。

我对大型数据库也有同样的问题。尽管将$row变量设置为大约400000条记录,但我的内存不足,但无缓冲查询修复了它

一些无缓冲查询示例代码为:

$sql = "SELECT SEQ, RECTYPE, ROSTERGRP, EMPNM, EMPNUM, DT, RDUTYCAT, ADUTYCAT FROM " .
        $tblRosters . " ORDER BY EMPNUM,DT";
$result  = mysql_unbuffered_query( $sql, $dbConn );
$svRow = array();
while ( $row = mysql_fetch_array( $result ) )
    {
         // your processing code here
    }
    // Unset, close db etc. if you are finished goes here.

看起来您不应该从该代码段中耗尽内存。是否有其他变量在每次迭代中不断增长?mysql查询是否会返回整个表->意味着结果将计入已用内存?这可能是一个愚蠢的建议,但这是我唯一能想到的:也许你可以尝试刷新输出缓冲区?有趣。由于您使用的是unset,所以在循环的第一次迭代之后,内存不应该真正增加。我只是好奇如果你使用(mysql\u unbuffered\u query())@Matthieu会发生什么,仅仅因为你的内存不足并不意味着这就是问题所在。这是一个想法,但我承认我太懒了。无论如何,错误发生在第400000行附近(请参阅问题更新),因此可能是循环中的某个问题,也许我可以解决?您目前的方法应该缓冲一些结果-删除缓冲以便不需要分页可能不是这样做的方法,无论如何,现在应该很容易了-@PalmTree已经为你做了:)为什么你认为删除分页不是一个好方法呢?不,我认为应该添加分页;我觉得移除缓冲不是正确的方法。删除缓冲将(大概)降低其性能-如果出于良好的技术原因,这是很好的,但太懒不是其中之一;-)我可能会发布您答案的“副本”,但我只能在代码行中发言:DI尝试添加unset以强制收集变量使用的内存,这在其他情况下是无法保证的(PHP GC)。不管怎样,请参见对另一个答案的评论和问题UpdateDomain!“如果可能的话,我希望避免实现分页。”我编写代码时没有这样做:D@PalmTree是的,很抱歉更新;)+1.谢谢你的努力。如果没有KillerX的解决方案,现在工作已经完成,我会欣然接受该代码;)投票给一个比我发布的更“传统”的解决方案。成功了!你的直觉是对的,我喜欢它,它回答了问题的根源。顺便说一句,我不理解没有解释的反对票。。。我不确定这是不是正确的方法,但是+1,因为它确实回答了最初的问题:)这似乎是“正确”的方法,尽管我以前没有听说过。说实话,我没有任何经验的功能,所以我不知道是否有任何PITFLAST,您可能会遇到以后,像MySQL连接死亡的中间处理。如果有人读到这篇文章时知道这类问题,请发帖,了解它会很有趣:)