robogame 2018-02-20 03:17:45 6304次浏览 3条评论 5 3 0

最近有一个需求,需要对一万条数据进行更新,在实际使用中发现使用AR循环操作的时候,内存直线上升,
后来查了相关资料,有同学写出来了。
(深入研究)记一个yii2下面的内存泄漏问题
最后发现,问题的根本不在于yii2的内存泄露,而是在于开启和关闭debug模式。
当开启debug模式的时候,在循环多条ar的时候会导致内存上涨,分析下原因,是debug模式会记录每一次循环中的单条ar的值,用于调试,所以就会导致内存上涨。
而关闭了debug模式之后,内存就不会了。
按照上述教程的示例:

$total = 10;
var_dump('开始内存'.memory_get_usage());
while($total){
    $ret=User::findOne(['id'=>910002]);
    var_dump('end内存'.memory_get_usage());
    unset($ret);
    $total--;
}

关闭debug模式,total设置为1000,内存峰值是4194616,
开启debug模式,total设置为1000,内存峰值为22023920;
所以,问题的根本在于要关闭debug模式。

觉得很赞
  • 评论于 2018-02-26 20:41 举报

    学习了,辛苦楼主

  • 评论于 2018-02-27 09:52 举报

    解决了1万条数据,解决不了10万,百万,千万的数据量传递,说明这种方式存在问题

    最好的方式,是在外层用shell脚本进行控制,先用shell读取php脚本获取总页数,
    然后,通过shell循环,每一个循环开启一个php进程,进行本页数据的同步,
    同步后,进程处理结束,shell进行下一个循环,是一个新的php进程,这样,千万数据也没事,你可以每页处理1000行,照样用AR。

    给你个例子看看:

    #!/bin/sh
    Cur_Dir=$(cd `dirname $0`; pwd)
    # get product all count.
    count=`$Cur_Dir/yii order/order/orderstatuscount`
    
    echo "There are $count Order to process"
    echo "##############ALL BEGINING###############";
    
    start=0
    
    for (( i=1; i<=$count; i++ ))
    do
       start=`$Cur_Dir/yii order/order/syncorderstatus $start`
       echo "Order_id $start done"
    done
    
    echo "##############ALL COMPLETE###############";
    
    1 条回复
    评论于 2018-06-30 12:26 回复

    嗯,你这个方法好,确实如此,千万级别的数据,还是这种最靠谱

    觉得很赞
  • 评论于 2018-02-28 10:32 举报

    之前做过的网站,就是记录历史信息数据很多,要去对比和修改多组数据,刚开始时候能运行,后期数据量大了,运行一部分就卡死不动,刚开始以为是服务器的问题,修改了环境内存,在运行一段时间又卡死。 后来细查,就是因为程序写的循环嵌套多,修改多,导致内存不足。。后来写的分页处理就好了。。一种ZHI销,一种卖二手车。

您需要登录后才可以评论。登录 | 立即注册