如果表为空,LockForUpdate会导致死锁

时间:2017-03-21 11:01:48

标签: laravel laravel-5 eloquent

目前我正在尝试上传一些与dropzone.js平行的图片。

这是代码的一部分,用于处理上传。

\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();

如果我不使用lockForUpdate(),我最终会在数据库中出现重复的位置。

上述解决方案存在的问题是,如果表为空,我会收到错误:

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

但仅限于我上传的第二张图片。

此外,自动增量ID会跳过值2,如1,3,4,5,6,7,...

表中的位置正确显示1,2,3,4 ....

我认为这个问题与最初的空表有关,因为我没有注意到这个问题,因为表中已有一些条目。

有什么建议我做错了吗?或者将lockForUpdate()与聚合函数结合使用可能完全错误......

1 个答案:

答案 0 :(得分:0)

我建议采用不同的交易方法。

try {

    app('db')->transaction(function ()) {
        $maxPos = GalleryImage::lockForUpdate()->max('pos');
        // other code (...)
        $galleryImage->pos = $maxPos + 1;
        $galleryImage->save();
    }
} catch (\Exception $e) {
    // display an error to user
}

如果在回调中发生任何异常,事务将回滚并释放任何锁。