PHP/Mysql 在尝试以块形式插入大量数据时"Fatal error: Allowed memory size exhausted .."



我正在将一个旧的PHP项目迁移到一个新的Laravel应用程序。有几百万条记录表user_category_views,我计划将其分块迁移。我用mysqli获取旧记录,并用LaravelDB::Statement插入。由于某种原因,在大约一百万次记录后,此代码将以异常情况出现:

致命错误:允许的内存大小268435456字节已用尽(试图分配73728字节(

什么东西溢出了内存?也许$result->free()不是我想的那样工作?

$count = 2000000; // actual number will be received from count(*) stmt
$vendors = [561 => '618', 784 => '512' /* and so on */ ];
$step = 5000;
for( $i=0; $i<=$count; $i+=$step ){
$q = "SELECT * FROM `user_category_views` LIMIT $i, $step;";
if ($result = $this->mysqli->query($q)) {
$stmt = "INSERT INTO vendor_views (`vendor_id`, `counter`, `created_at`) VALUES";
/* fetch associative array */
while ($row = $result->fetch_assoc()) {
$vendor_id = null;
$id = $row['user_category_id'];
// Here I'm trying to prevent Laravel 
// from throwing the exception if the entry 
// is not found in $vendors array. 
// This habit I've gained from js coding  
try{
$vendor_id = $vendors[$id];
} catch (Exception $e) {
continue;
}
if(empty($vendor_id)) continue;
$counter = $row['counter'];
$created = $row['created'] ;
$stmt .= " ($vendor_id, $counter, '{$created}'),";
}
$result->free();
DB::statement( trim($stmt, ",") );
$stmt = null;
}
}

感谢Nigel Ren,他指出我滥用了try/catch构造

所以不是

.....
try{
$vendor_id = $vendors[$id];
} catch (Exception $e) {
continue;
}
....

我现在使用

$vendor_id = $vendors[$id]??null;

并且不再存在内存泄漏问题。不知道,为什么,但现在它工作

您的问题是因为内存有限。尝试在PHP文件的顶部设置:

ini_set('memory_limit', '-1');

增加PHP的内存限制。

如果上述解决方案不起作用。也许你的RAM坏了。请检查一下。你也可以减少你的步数,比如$step=5000;至$step=1000;我觉得更好

希望能有所帮助。感谢

最新更新