0

I'm trying to convert our database from ID to UUID. When I run the following code to update the database is skips random rows.

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]);
        }
    });

Last time i checked ~290 were skipped out of 236196 total.

I've tried to used chunkById, but the same thing happened. The update function is always returning true, so I must assume that Laravel thinks every row is updated when executed.

Jonas Holm
  • 53
  • 1
  • 1
  • 11
  • Are you using soft deletes or any other global scopes that could be limiting the results? – matticustard Jan 27 '21 at 18:28
  • The AppUser model don't have softdelete anymore. I checked the DB and only 2 rows have been soft deleted back in the days. No global scopes are used either. – Jonas Holm Jan 28 '21 at 08:01

2 Answers2

1

There's a big warning in the Laravel documentation on chunking:

When updating or deleting records inside the chunk callback, any changes to the primary key or foreign keys could affect the chunk query. This could potentially result in records not being included in the chunked results.

You'll need to find another way to update your keys in batches. I've used the technique described in an answer to this question: How to chunk results from a custom query in Laravel when I could not use the callback required by the chunk method, although in that case it was not for an update query, only a select.

Tony
  • 9,672
  • 3
  • 47
  • 75
1

This is what i ended up doing

$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]);
        }
    }
Jonas Holm
  • 53
  • 1
  • 1
  • 11