Laravel更新分块结果跳过行



我正在尝试将我们的数据库从ID转换为UUID。当我运行以下代码来更新数据库时,它会跳过随机行。

AppUser::select('id')->orderBy('created_at')->chunk(1000, function ($appUsers) {
foreach ($appUsers as $appUser) {
$uuid = Str::orderedUuid();
DB::table('files')->where('fileable_type', AppUserInfo::class)->where('fileable_id', $appUser->id)->update([
'fileable_id' => $uuid
]);
DB::table('app_users')->where('id', $appUser->id)->update(['id' => $uuid]);
}
});

上次我检查时,共有236196个中有290个被跳过。

我尝试使用chunkById,但同样的事情发生了。update函数总是返回true,所以我必须假设Laravel认为每一行在执行时都被更新了。

在Laravel文档中有一个关于分块的大警告:

当更新或删除块回调中的记录时,对主键或外键的任何更改都可能影响块查询。这可能会导致记录不包含在分块结果中。

你需要找到另一种方法来批量更新你的密钥。我在回答这个问题时使用了描述的技术:如何在Laravel中从自定义查询中块结果,当我不能使用chunk方法所需的回调时,尽管在这种情况下它不是用于update查询,只有select

这就是我最后做的

$appUsers = AppUser::select('id')->get();
$chunkSize = 1000;
$numberOfChunks = ceil($appUsers->count() / $chunkSize);
$chunks = $appUsers->split($numberOfChunks);

foreach($chunks as $chunk) {
foreach($chunk as $appUser) {
$uuid = Str::orderedUuid();
DB::table('files')->where('fileable_type', AppUserInfo::class)->where('fileable_id', $appUser->id)->update([
'fileable_id' => $uuid
]);
DB::table('app_users')->where('id', $appUser->id)->update(['id' => $uuid]);
}
}

最新更新