lockForUpdate()
和 sharedLock()
是 Laravel Eloquent 中用于设置排他或共享锁的函数(文档在这里)。
然而,我找不到一个好的语法来对单个已实例化的 Eloquent 模型应用此功能。考虑以下示例代码:
DB::transaction(function() {
// Find the user with ID = 1.
$user = User::find(1);
$user->lockForUpdate()->update([
'balance' => $user->balance + 1
]);
// ... some more stuff happens here in the transaction
});
上述代码将不会按预期工作。在此处,
lockForUpdate()
返回一个新的查询构建器,这将导致所有用户的余额增加1。我想在此事务的持续时间内读取锁定
balance
属性,以便发生并行处理的任何其他事务都不会通过计算错误的结果而使账户余额出现偏差。那么,如何确保在更新此用户时锁定balance
属性?我知道可以调用以下函数,但为此创建一个新查询似乎有点违反直觉,其中还包括$user
变量:$updated = User::query()->where('id', 1)->lockForUpdate()->update([
'balance' => $user->balance
]);
注意:我希望在这里不考虑
->increment()
和->decrement()
。我无法使用这些函数,因为我需要Eloquent的updating
/updated
/saving
/saved
事件挂钩正常触发(如果使用这些函数则无法触发)。这是可以预料的,如需更多信息,请参见https://github.com/laravel/framework/issues/18802#issuecomment-593031090。