在使用laravel执行长时间命令行脚本操作数据会导致内存溢出,辛苦各位同学指点
laravel版本:6.20.19
, 8.35.1
PHP版本:7.3.16
, 7.4.16
操作系统:macOS 11.2.3
, centos7
脚本类型:artisan console command
问题描述:
我需要一个长时间监控某项数据的脚本,但是在使用过程中出现内存泄露,尝试了以下方法:
- 销毁了所有的不再使用的变量
- 使用模型静态方法:firstOrCreate 之前使用了unsetEventDispatcher
- DB的insert之前使用了unsetEventDispatcher;
- 原生PDO操作
- 修改了flare.php将所有的true都改成了false
- 使用事件机制,在监听器中创建db对象,执行sql操作,销毁db对象,销毁事件对象
发现内存一直都在增加,没有得到释放,但是不使用框架时,使用PDO操作,内存得到释放,控制的很好。
后面根据 @振翅飞翔 的评论提醒下,删除了 composer remove --dev facade/ignitio
也没有变化,不过却让我意识到可能还是日志的问题,于是把代码里面的Log调用注释掉,发现内存稳定了。
但是仍旧不知道应当如何解决此问题,因为在项目中日志是必要的。
目前基本的结论是:
- 数据库操作确实会导致内存溢出
- Log组件也会导致内存溢出
以下是示例代码:
while(true){
$signal_record = [
'column1' => mt_rand(1,200),
'column2' => 'testB',
'type' => 'LIMIT',
'signal' => 'IN',
'opening_time' => date('Y-m-d H:i:s'),
'closing_time' => date('Y-m-d H:i:s'),
'strategies_name' => 'B',
];
$this->info(date('Y-m-d H:i:s') . ' 内存占用' . memory_get_usage());
TradeSignalRecords::unsetEventDispatcher();
$r = TradeSignalRecords::create($signal_record);
//$r = ModelsTradeSignalRecords::firstOrNew($signal_record);
Log::debug( ' 发现信号 ' .json_encode($signal_record));
$r = null;
$this->info(date('Y-m-d H:i:s') . ' 内存占用' . memory_get_usage());
sleep(1);
}
使用DB操作的示例代码
while(true){
$signal_record = [
'column1' => mt_rand(1,200),
'column2' => 'testB',
'type' => 'LIMIT',
'signal' => 'IN',
'opening_time' => date('Y-m-d H:i:s'),
'closing_time' => date('Y-m-d H:i:s'),
'strategies_name' => 'B',
];
$this->info(date('Y-m-d H:i:s') . ' 内存占用' . memory_get_usage());
$connection_name = 'test';
$table_name = 'trade_records';
$connection = DB::connection($connection_name)->table($table_name);
$connection->getConnection()->unsetEventDispatcher(); // https://learnku.com/laravel/t/52660?order_by=vote_count
$this->_connection->insert($signal_record);
Log::debug( ' 发现信号 ' .json_encode($signal_record));
$connection = null;
$signal_record = null;
$connection_name = null;
$table_name = null;
$this->info(date('Y-m-d H:i:s') . ' 内存占用' . memory_get_usage());
sleep(1);
}
使用PDO版本代码示例,此代码在laravel command中内存没有回收,但是不用框架时内存得到了释放
while(true){
echo date('Y-m-d H:i:s') . ' 内存占用' . memory_get_usage() . "\r\n";
$conn = new \PDO("mysql:host=localhost;dbname=test", 'root', '123456');
$conn->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
$sql = "INSERT INTO trade_records (column1, `column2`, type,`signal`,opening_time,closing_time,strategies_name) VALUES (" . mt_rand(1,100). ", 'testB','LIMIT','IN','2021-04-01 19:15:00','2021-04-01 19:15:00','B')";
// 在laravel框架中使用下面这句日志记录
// Log::debug( ' 发现信号 ' .json_encode($signal_record));
$r = $conn->exec($sql);
$conn = null;
$r = null;
$sql = null;
sleep(1);
}
参考资料:
有什么好办法解决进程内存一直增长
DB 添加数据如何实时释放掉内存?
PHP 常驻任务不会释放内存的吗?
Laravel 控制台程序 循环执行 ORM 查询 内存溢出
记一次laravel 内存泄漏
【PHP内存泄漏案例】PHP对象递归引用造成内存泄漏
Laravel7使用日志内存会一直往上增长最后导致内存泄漏
推荐文章: