Allowed memory size of 134217728 bytes 错误解决心得

错误如下:

FatalErrorException in String.php line 575: 
Allowed memory size of 134217728 bytes

服务器 :linux + nginx + php-fpm

报的错误很简单,php.ini中默认内存限制是128M,改大?方案不可取,按照我java程序员跑来写php的野路子来说,肯定我的代码出问题了。

网上查了查有人说unset($var),没有释放变量,内存没有释放,越用越高。 有道理!

$tyusers = User::orderBy(isset($data['sort'])?$data['sort']:"uid",isset($data['order'])?$data['order']:"asc")
            ->where(function($query) use($data) {
                $query->where('subscribe',1);
                if(isset($data['issteam'])){
                    if($data['issteam'] == 0 ){
                        $query->whereNull('steamid');
                    }else if($data['issteam'] == 1){
                        $query->whereNotNull('steamid');
                    }
                }
            })
            ->offset(($page - 1) * $rows)->limit($page * $rows)->get();
        $cellData = [];
        array_push($cellData,array("ID","邮箱","SteamID","注册时间","昵称"));
        foreach ($tyusers as $tyuser){
            array_push($cellData,array($tyuser->uid,$tyuser->email,$tyuser->steamid." ",$tyuser->created_at,$tyuser->name));
        }
        Excel::create(date("Y-m-d-His").'-用户列表'.(($page - 1) * $rows).'到'.($page * $rows),function($excel) use ($cellData){
            $excel->sheet('score', function($sheet) use ($cellData){
                $sheet->rows($cellData);
            });
        })->export('xls');
        // 释放对象
        unset($tyusers);
        unset($cellData);

于是乎我高高兴兴的加上后面两句,so easy。然后发现还是不行!!!还是报错!!! joy: :joy: :joy:
仔细一想,php作为世界上最美丽的语言不会因为我没有主动unset($var)就撑爆内存吧,即使我没有及时unset($var),我相信当此次访问结束时他也会被回收。(对于php的内存机制不是很了解,但我依然这样相信。)

后来经过仔细观察,10000行一页,我导出第一页没问题,只有第二页有问题,想了想上面是字符串类报错。最后定位问题,查询的结果集太大,之前user表里面只有七八个字段,后来整合论坛,直接又加进来不下二十个字段,所有字段都查询出来肯定撑爆内存。

最后修改代码:

$*****->get(["uid","loginid","steamid","created_at","name"]);

总结:用什么就拿什么,不用就别浪费资源,培养良好的代码习惯。

triumph: :triumph: :triumph:

本作品采用《CC 协议》,转载必须注明作者和本文链接
本帖由 Summer 于 6年前 加精
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
讨论数量: 10

查询出需要的字段,这是明智的选择。mysql 优化就要避免 select * 的情况

6年前 评论

确实应该养成好习惯啊! 该严谨的地方还是得严谨

6年前 评论
leung0826

也可以使用,ini_set (),但用什么取什么要更好点

6年前 评论

可以试试分次导出

6年前 评论

$query->each(Closure) 也能解决这个问题,each 默认每次拉取 1000 条

6年前 评论

下次数据量大的时候还是一样会撑爆

6年前 评论

@ouminghai 最多导出10000条,这种操作,没有界限就没有尽头。

6年前 评论

@KubiLi 是的,之前我就是每次导出最多5000条,不然像php这种不限制内存,能把服务器内存吃完。

6年前 评论

试试手动GC

6年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!