Tuesday, March 21, 2017

LockForUpdate causes Deadlock if table is empty

Currently I am trying to upload some images parallel with dropzone.js.

This is part of the code, that handles the upload.

\DB::beginTransaction();
        $maxPos = GalleryImage::lockForUpdate()->max('pos');

    try {
        // some other code
        // .... 

        $galleryImage->pos = $maxPos + 1;
        $galleryImage->save();
    } catch (\Exception $e) {
        \DB::rollBack();
        \Log::error($e->getMessage());
        return response('An error occured', 500);
    }
    \DB::commit();

If I do not use the lockForUpdate() I end up with duplicate positions in database.

The problem with above solution ist, that if the table is empty I get the error:

Serialization failure: 1213 Deadlock found when trying to get lock; try restarting transaction 

But only for the second image I am uploading.

Additionally the autoincrement id skips the value 2 and goes like 1,3,4,5,6,7, ...

The Positions in the table are shown correctly 1,2,3,4....

I think the problem has to do with the table beeing empty initially, as I did not notice this problem, when there are already some entries in the table.

Any suggestions what I am doing wrong? Or Maybe using lockForUpdate() in combination with an aggregate function is wrong at all...



via shock_gone_wild

Advertisement