我正在将一个旧的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;我觉得更好
希望能有所帮助。感谢