Laravel lockforupdate (Pessimistic Locking)

我试图弄清楚如何正确使用/测试锁定更新,但我发现功能不像我预期的那样

这只是测试

public function index() {
        return dd(\DB::transaction(function() {
            if (\Auth::guard('user')->check()) {
                $model = \App\Models\User::find(1)->lockForUpdate();
                sleep(60);
                $model->point = 100000;
                $model->save();
            } else {
                $model = \App\Models\User::find(1);
                $model->point = 999;
                $model->save();
            }

            return $model;
        }));
}

我尝试在2浏览器中进行测试,浏览器1用户登录和浏览器2未登录,浏览器1点击刷新,然后会有锁定更新和睡眠60秒前更新

在60秒内,我去浏览器2并点击刷新,但是记录未锁定,我检查phpmyadmin并更新记录(在浏览器1的60秒锁定触发内)

但 60 秒后,记录已被浏览器 1(点 100000)再次修改

所以我误解了锁的更新是用来的?或者我测试得不正确?

我所期望的是,浏览器2不应该在前60秒内修改该行(带有加载图标或错误抛出的空白页?

https://laravel.com/docs/5.2/queries#pessimistic-locking

我做了一些研究,但仍然无法理解sharelock(锁定在共享模式下)和lockForUpdate(用于更新)之间的区别

顺便说一句,我确认数据库是innodb


答案 1

这项工作,最后,但仍然不明白共享锁(锁定在共享模式)和lockForUpdate(FOR UPDATE)有什么不同

    public function index() {
        return dd(\DB::transaction(function() {
            if (\Auth::guard('user')->check()) {
                $model = \App\Models\User::lockForUpdate()->find(1);
                sleep(30);
                $model->point = 100000;
                $model->save();
            } else {
                $model = \App\Models\User::lockForUpdate()->find(1);
                $model->point = $model->point + 1;
                $model->save();
            }

            return $model;
        }));
    }

答案 2

所以这是一个老问题,但我相信我的答案可以澄清->lockForUpdate()是如何工作的。

来自Laravel文档:

共享锁可防止在提交事务之前修改所选行。

因此,正如它所写的那样 - 从您调用它到交易完成,锁将处于活动状态。

记得:

->find(1)工作方式类似于 、 、 等 - 它执行查询->first()->get()->insert()->save()

->lockForUpdate()工作方式类似于 、 等 - 它添加到查询中,但不执行它->where()->select()join()

$model = \App\Models\User::find(1)->lockForUpdate();- 您尝试在查询已执行后添加锁定

$model = \App\Models\User::lockForUpdate()->find(1);- 在执行查询之前添加锁定,因此在事务完成之前锁定处于活动状态

不同之处在于,在第一种情况下当你教导它是->lockForUpdate()


推荐