php脚本中的内存泄漏

php脚本中的内存泄漏,php,mysql,memory-leaks,Php,Mysql,Memory Leaks,我有一个php脚本,它运行一个mysql查询,然后循环结果,在该循环中还运行几个查询: $sqlstr = "SELECT * FROM user_pred WHERE uprType != 2 AND uprTurn=$turn ORDER BY uprUserTeamIdFK"; $utmres = mysql_query($sqlstr) or trigger_error($termerror = __FILE__." - ".__LINE__.": ".mysql_err

我有一个php脚本,它运行一个mysql查询,然后循环结果,在该循环中还运行几个查询:

    $sqlstr = "SELECT * FROM user_pred WHERE uprType != 2 AND uprTurn=$turn ORDER BY uprUserTeamIdFK";
    $utmres = mysql_query($sqlstr) or trigger_error($termerror = __FILE__." - ".__LINE__.": ".mysql_error());
    while($utmrow = mysql_fetch_array($utmres, MYSQL_ASSOC)) {
// some stuff happens here    
//  echo memory_get_usage() . " - 1241<br/>\n";
        $sqlstr = "UPDATE user_roundscores SET ursUpdDate=NOW(),ursScore=$score WHERE ursUserTeamIdFK=$userteamid";
        if(!mysql_query($sqlstr)) {
            $err_crit++;
            $cLog->WriteLogFile("Failed to UPDATE user_roundscores record for user $userid - teamuserid: $userteamid\n");
            echo "Failed to UPDATE user_roundscores record for user $userid - teamuserid: $userteamid<br>\n";
            break;
        }
    unset($sqlstr);
    //  echo memory_get_usage() . " - 1253<br/>\n";
// some stuff happens here too
}
$sqlstr=“从用户_pred中选择*,其中uprType!=2和uprTurn=$turn ORDER BY uprpuserteamidfk”;
$utmres=mysql\u查询($sqlstr)或触发器\u错误($termerror=\uuuuuuu文件\uuuuuuuuu.-“.uuuuuu行\uuuuuuu.:”.mysql\u错误());
而($utmrow=mysql\u fetch\u数组($utmres,mysql\u ASSOC)){
//这里发生了一些事情
//回显内存\u get\u用法().“-1241
\n”; $sqlstr=“UPDATE user\u roundscores SET ursUpdDate=NOW(),urscore=$score,其中ursUserTeamIdFK=$userteamid”; if(!mysql_query($sqlstr)){ $err_crit++; $cLog->WriteLogFile(“未能更新用户$userid-teamuserid:$userteamid\n的用户\u得分记录”); echo“未能更新用户$userid-teamuserid:$userteamid的用户\u总分记录
\n”; 打破 } 未结算($sqlstr); //回显内存\u get\u用法().“-1253
\n”; //这里也发生了一些事情 }
更新查询从不失败

由于某些原因,在两次调用
memory\u get\u usage
之间添加了一些内存。因为大循环运行了大约500000次或更多次,所以最终它确实增加了大量内存。这里有我遗漏的东西吗
内存可能不是在两个调用之间添加的,而是在脚本中的另一个点添加的吗

编辑:一些额外信息: 在循环之前大约是5mb,循环之后大约是440mb,每次更新查询都会增加大约250字节。(剩余内存将添加到循环中的其他位置)。 我没有发布更多“其他东西”的原因是因为它大约有300行代码。我发布此部分是因为它看起来是添加内存最多的地方。

我认为您应该在循环过程中的某个时间点尝试调用。-从评论中:

值得注意的是,mysql_query() 仅返回
选择的资源
显示
解释
描述
查询

因此,对于更新查询,没有可释放的结果


无论如何,你的方法不是最好的开始。试试mysqli参数化语句,或者(甚至更好)直接更新数据库中的行。看起来循环中的所有SQL都可以用一个UPDATE语句来处理。

在每次迭代中,您可能会看到额外使用的内存,部分原因是PHP尚未(尚未)垃圾收集不再引用的内容。

最好的方法可能是获取所有用户ID并将其刷新到一个文件中。 然后运行一个新的脚本,该脚本与管道分叉,生成x数量的工作无人机。然后,在他们完成每个列表时,只需给他们一个小的要处理的用户名列表。使用多个CPU/核心/服务器,您可以更快地完成任务。如果一个工人失败了,只需启动一个新的工人。
要将其他服务器用作辅助线程,您可以从辅助线程使用curl/fopen/soap/etc调用它们。

只有当它通过“内存耗尽”错误终止脚本时,此内存泄漏才会成为问题。PHP很乐意自己对任何未使用的对象/变量进行垃圾收集,但收集器在必须进行垃圾收集之前不会启动—垃圾收集可能是一项非常昂贵的操作

即使您不断重复使用相同的对象/变量,内存使用率也会上升,这是很正常的——直到内存使用率超过一定水平,收集器才会启动并清理房间

我猜想,如果您将用户ID分批放入组中,并发布更少的更新,每次更改更多记录,您可以使事情运行得更快。e、 g.执行以下操作:

UPDATE user_roundscores SET ursUpdDate=NOW() WHERE ursUserTeamIdFK IN (id1, id2, id3, id4, id5, etc...)
而不是每个用户更新一次。通过DB接口层的往返次数越少,服务器上的时间越多=运行速度越快

同样,考虑一下现在扩展到数百万用户的影响,正如你在评论中所说的那样。一百万个单独的更新将花费大量的时间来运行,因此
NOW()
将不是一个“常量”。如果完整运行需要5分钟,那么您将获得各种各样的
ursUpdDate
时间戳。您可能想考虑缓存一个代码< >()(代码)>在服务器端变量中调用,并发布针对该变量的更新:

 SELECT @cachednow :p NOW();
 UPDATE .... SET ursUpDate = @cachednow WHERE ....;

unset
调用没有意义/不相关。尝试一下-它可能会有一些效果。

来自:

参数

real\u usage将此设置为TRUE以获取 从中分配的内存的实际大小 系统。如果未设置或为FALSE,则只有 已报告emalloc()使用的内存


将此参数设置为true后,脚本显示的内存没有像我预期的那样增加。

循环中发生了很多事情,我只是缩短了查询以使其更易于阅读,并将重点放在我注意到内存被添加的部分。我的理解是,在循环之后,我只能在$utmres上使用mysql\u free\u result(),在更新查询中不需要使用它。mysql\u free\u result对update语句没有帮助。“值得注意的是,mysql_query()只返回用于选择、显示、解释和描述查询的资源。”@Jasper:当您将循环简化为纯SQL活动时,泄漏是否仍然存在?也许泄漏是发生在其他“东西”中?我想我应该开始剥离“其他东西”的一部分,看看是否有帮助。但这对我来说毫无意义,因为我在这段代码之前和之后调用了内存的用法;在这样的循环中,由于变量在每次迭代中被重新分配,所以只能暂时释放内存。您是否验证了您的服务器上是否启用了垃圾收集器(默认情况下是启用的)?我看不出这里有问题。请发布更多的while循环,并指出它使用了多少内存。在第一次查询之前、第一次查询之后和循环之后,返回的内存使用率是多少?@webbiedave在循环之前大约是5mb,在循环之后