我正在试图弄清楚如何正确使用/测试lockforupdate,但我发现它的功能不像我预期的那样
这只是测试
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(Point 100000)再次修改了记录
所以我误解了lockforupdate用于?或者我测试不正确?
我的预期是在前60秒内浏览器2不应修改该行(加载favicon的空白页或错误抛出?)
https://laravel.com/docs/5.2/queries#pessimistic-locking
我做了一些研究,但仍然无法理解sharedLock(LOCK IN SHARE MODE)和lockForUpdate(FOR UPDATE)之间有什么不同
顺便说一下我确认数据库是innodb
答案 0 :(得分:11)
这项工作,最后,但仍然不明白什么是sharedLock(LOCK IN SHARE MODE)和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;
}));
}
答案 1 :(得分:3)
所以这是个老问题,但我相信我的回答可以阐明 ->lockForUpdate()
的工作原理
来自 Laravel 文档:
<块引用>共享锁防止所选行被修改,直到 您的交易已提交。
正如它所写的那样 - 从您调用它直到您的交易完成,锁都将处于活动状态。
记住:
->find(1)
与 ->first()
、->get()
、->insert()
、->save()
等类似 - 它执行查询
->lockForUpdate()
与 ->where()
、->select()
、join()
等类似 - 它添加到查询中,但不执行它< /p>
$model = \App\Models\User::find(1)->lockForUpdate();
- 您尝试在查询执行后添加锁
$model = \App\Models\User::lockForUpdate()->find(1);
- 您在执行查询之前添加锁,因此锁在事务完成之前一直处于活动状态
不同之处在于,在第一个场景中,->lockForUpdate()
没有被执行,当你教导它是
答案 2 :(得分:1)
共享锁:
DB::table('users')->where('votes', '>', 100)->sharedLock()->get();
LockForUpdate:
DB::table('users')->where('votes', '>', 100)->lockForUpdate()->get();