关于Yii2框架跑脚本时内存泄漏问题的分析与解决


Posted in PHP onDecember 01, 2019

现象

在跑 edu_ocr_img 表的归档时,每跑几万个数据,都会报一次内存耗尽

PHP Fatal error:  Allowed memory size of 134217728 bytesexhausted (tried toallocate 135168 bytes)

跟踪代码发现,是在插入时以下代码造成的:

EduOCRTaskBackup::getDb()->createCommand()->batchInsert(EduOCRTaskBackup::tableName(), $fields, $data)->execute();

execute 之后会造成使用内存涨上去,并且在之后 unset 所有变量内存也会有一部分不会删除,直到内存耗尽。

于是跟踪到 Yii2中execute的具体代码块发现在记录 log 的时候会将使用很高的内存,分析代码之后得出造成泄漏的代码块如下:

造成泄漏的代码块

/**
 * Logs a message with the given type and category.
 * If [[traceLevel]] is greater than 0, additional call stack information about
 * the application code will be logged as well.
 * @param string|array $message the message to be logged. This can be a simple string or a more
 * complex data structure that will be handled by a [[Target|log target]].
 * @param integer $level the level of the message. This must be one of the following:
 * `Logger::LEVEL_ERROR`, `Logger::LEVEL_WARNING`, `Logger::LEVEL_INFO`, `Logger::LEVEL_TRACE`,
 * `Logger::LEVEL_PROFILE_BEGIN`, `Logger::LEVEL_PROFILE_END`.
 * @param string $category the category of the message.
 */
public function log($message, $level, $category = 'application')
{
 $time = microtime(true);
 $traces = [];
 if ($this->traceLevel > 0) {
  $count = 0;
  $ts = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
  array_pop($ts); // remove the last trace since it would be the entry script, not very useful
  foreach ($ts as $trace) {
   if (isset($trace['file'], $trace['line']) && strpos($trace['file'], YII2_PATH) !== 0) {
    unset($trace['object'], $trace['args']);
    $traces[] = $trace;
    if (++$count >= $this->traceLevel) {
     break;
    }
   }
  }
 }
 
 // 这里是造成内存的罪魁祸首
 $this->messages[] = [$message, $level, $category, $time, $traces];
 if ($this->flushInterval > 0 && count($this->messages) >= $this->flushInterval) {
  $this->flush();
 }
}

造成内存泄漏的原因分析

在 Yii2框架中的 vendor/yiisoft/yii2/log/Logger.php:156 log函数的156行之后会判断 count($this->messages) >= $this->flushInterval

即:内存中存储的 message 的条数要大于等于预设的 $this->flushInterval 才会将内存中的message 刷到磁盘上去。

如果在刷新到磁盘之前就已经将 php.ini 设置的 128M 内存打满的话,会直接报错申请内存耗尽。

很多关于 YII2其他原因的内存泄漏的讨论
https://github.com/yiisoft/yii2/issues/13256

解决方案

在程序开始时,设置 flushInterval 为一个比较小的值

\Yii::getLogger()->flushInterval = 100; // 设置成一个较小的值

在程序执行过程中,每次 execute 之后对内存中的 message 进行 flush

\Yii::getLogger()->flush(true); // 参数传 true 表示每次都会将 message 清理到磁盘中

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对三水点靠木的支持。

PHP 相关文章推荐
最小化数据传输――在客户端存储数据
Oct 09 PHP
PHP 在5.1.* 和5.2.*之间 PDO数据库操作中的不同之处小结
Mar 07 PHP
9条PHP编程小知识及易犯的小错误
Jan 22 PHP
PHP实现从远程下载文件的方法
Mar 12 PHP
php遍历删除整个目录及文件的方法
Mar 13 PHP
php通过ksort()函数给关联数组按照键排序的方法
Mar 18 PHP
php中如何执行linux命令详解
Nov 06 PHP
thinkPHP框架RBAC实现原理分析
Feb 01 PHP
CI(CodeIgniter)框架中URL特殊字符处理与SQL注入隐患分析
Feb 28 PHP
php依赖注入知识点详解
Sep 23 PHP
Yii框架组件的事件机制原理与用法分析
Apr 07 PHP
php中pcntl_fork详解
Apr 01 PHP
详解no input file specified 三种解决方法
Nov 29 #PHP
设定php简写功能的方法
Nov 28 #PHP
如何在centos8自定义目录安装php7.3
Nov 28 #PHP
PHP的new static和new self的区别与使用
Nov 27 #PHP
Laravel 微信小程序后端实现用户登录的示例代码
Nov 26 #PHP
Laravel 微信小程序后端搭建步骤详解
Nov 26 #PHP
php 使用expat方式解析xml文件操作示例
Nov 26 #PHP
You might like
php session和cookie使用说明
2010/04/07 PHP
让你成为更出色的PHP开发者的10个技巧
2011/02/25 PHP
php生成EAN_13标准条形码实例
2013/11/13 PHP
Drupal7连接多个数据库及常见问题解决
2014/03/02 PHP
PHP面向对象程序设计实例分析
2016/01/26 PHP
laravel中的错误与日志用法详解
2016/07/26 PHP
Some tips of wmi scripting in jscript (1)
2007/04/03 Javascript
关于二级域名下使用一级域名下的COOKIE的问题
2011/11/07 Javascript
jQuery-Easyui 1.2 实现多层菜单效果的代码
2012/01/13 Javascript
用js来获取上传的文件名纯粹是为了美化而用
2013/10/23 Javascript
Javascript图片上传前的本地预览实例
2014/06/16 Javascript
JavaScript驾驭网页-CSS与DOM
2016/03/24 Javascript
每日十条JavaScript经验技巧(一)
2016/06/23 Javascript
深入学习jQuery中的data()
2016/12/22 Javascript
Vue.js 2.5新特性介绍(推荐)
2017/10/24 Javascript
VS Code转换大小写、修改选中文字或代码颜色的方法
2017/12/15 Javascript
layui实现点击按钮给table添加一行
2018/08/10 Javascript
js 闭包深入理解与实例分析
2020/03/19 Javascript
Vue使用CDN引用项目组件,减少项目体积的步骤
2020/10/30 Javascript
Python 常用string函数详解
2016/05/30 Python
关于Python如何避免循环导入问题详解
2017/09/14 Python
Python之inspect模块实现获取加载模块路径的方法
2018/10/16 Python
Python变量类型知识点总结
2019/02/18 Python
Python如何使用k-means方法将列表中相似的句子归类
2019/08/08 Python
python从zip中删除指定后缀文件(推荐)
2019/12/05 Python
python 解决pycharm运行py文件只有unittest选项的问题
2020/09/01 Python
前端实现弹幕效果的方法总结(包含css3和canvas的实现方式)
2018/07/12 HTML / CSS
html5实现输入框fixed定位在屏幕最底部兼容性
2020/07/03 HTML / CSS
中学教师岗位职责
2013/11/26 职场文书
竞选部门副经理的自荐书范文
2014/02/11 职场文书
大学生党员自我批评
2014/02/14 职场文书
专业求职信撰写要诀
2014/02/18 职场文书
交通安全寄语大全
2014/04/08 职场文书
驾驶员培训方案
2014/05/01 职场文书
弘扬民族精神演讲稿
2014/05/07 职场文书
巾帼文明岗事迹材料
2014/12/24 职场文书