流动 - lavarel
type: channel
link: https://www.liudon.org/tag/lavarel/
items: Lavarel Eloquent ORM常驻进程下的内存溢出问题
items: 让Lavarel Eloquent ORM 支持 mongodb数据库

Lavarel Eloquent ORM常驻进程下的内存溢出问题
type: item
date: 2019-01-08T15:57:57+08:00
description: Laravel 的 Eloquent ORM 提供了漂亮、简洁的 ActiveRecord 实现来和数据库交互。每个数据库表都有一个对应的「模型」用来与该表交互。你可以通过模型查询数据表中的数据，并将新记录添加到数据表中。业务里使用了ORM来进行数据库操作，有个cron运行一段时间后就报内存溢出的错误，之前一直没时间彻底解决，这次有时间彻底搞清楚了。代码类似：$capsule = new Capsule; foreach ($database[$env] as $name => $conf) { // 创建链接 $capsule->addConnection($conf, $name); } // 设置全局静态可访问 $capsule->setAsGlobal(); // 启动Eloquent $capsule->bootEloquent(); while (1) { try { $service = new PostModel(); $dataList = $service->where('status', 1)->limit(100)->get()->toArray(); } catch (Exception $e) { continue; } if (!$dataList) { break; } foreach ($dataList as $data) { // do something // 最后会更新status字段=2 } }断点调试，发现每查询一次数据，内存就会增长3M左右，运行30次左右，就会报内存溢出。怀疑是不是ORM这里会记录每次的查询结果，搜索了一下，发现还真有类似功能。Laravel Eloquent display query log最终实现代码：$capsule = new Capsule; foreach ($database[$env] as $name => $conf) { // 创建链接 $capsule->addConnection($conf, $name); // 关闭查询日志，常驻进程会导致内存溢出 $capsule->getConnection($name)->disableQueryLog(); } // 设置全局静态可访问 $capsule->setAsGlobal(); // 启动Eloquent $capsule->bootEloquent(); while (1) { try { $service = new PostModel(); $dataList = $service->where('status', 1)->limit(10)->get()->toArray(); } catch (Exception $e) { continue; } if (!$dataList) { break; } foreach ($dataList as $data) { // do something // 最后会更新status字段=2 } }

让Lavarel Eloquent ORM 支持 mongodb数据库
type: item
date: 2018-08-10T16:39:00+08:00
description: Laravel 的 Eloquent ORM 提供了漂亮、简洁的 ActiveRecord 实现来和数据库的互动。 每个数据库表会和一个对应的「模型」互动。组件说明业务侧还在用PHP5.3，composer.json文件内容如下：{ "require": { "illuminate/database": "4.1.*", "jenssegers/mongodb": "1.3.*" } }实际安装的版本如下。组件版本illuminate/databasev4.1.30jenssegers/laravel-mongodbv1.3.2使用方式：配置文件conf/database.php新增mongodb配置。<?php $database = array( 'mongodb' => array( 'driver' => 'mongodb', 'host' => '100.98.173.13', 'port' => 5566, 'database' => 'bigdata', ), )自动加载数据库，新增mongodb数据库类型。include conf/database.php; $capsule = new Capsule; // 支持mongodb数据库，如果name是mongodb，交给Jenssegers\Mongodb\Connection来处理 $capsule->getDatabaseManager()->extend('mongodb', function($config) { return new Jenssegers\Mongodb\Connection($config); }); foreach ($database[$env] as $name => $conf) { // 创建链接 $capsule->addConnection($conf, $name); } // 设置全局静态可访问 $capsule->setAsGlobal(); // 启动Eloquent $capsule->bootEloquent();model继承Jenssegers\Mongodb\Model.<?php class UserModel extends Jenssegers\Mongodb\Model { /** * table * * @var string */ protected $table = 'users'; /** * connection * * @var string */ protected $connection = 'mongodb'; }上面是按网上找到的资料配置的，然后跑起来后报PHP Fatal error: Call to a member function connection() on a non-object in /web/xxx/vendor/illuminate/database/Illuminate/Database/Eloquent/Model.php on line 2810的错误。断点定位了半天，才解决掉问题，这里记录一下。先看下2810行的代码是什么。2808 public static function resolveConnection($connection = null) 2809 { 2810 return static::$resolver->connection($connection); 2811 }注意这里用的是static::$resolver，关于php的static和self的区别可以参考这篇文章，这里不做过多描述。php中self与static的区别 解决方法：修改vendor\jenssegers\mongodb\src\Jenssegers\Mongodb\Model.php文件，注释下面这行代码。protected static $resolver;