首页 > 解决方案 > Laravel lockForUpdate + 事务

问题描述

我们像这样使用 lockForUpdate :

DB::beginTransaction();

try {
    $balance = UserBalance::where('user_id', 2)
                    ->lockForUpdate()
                    ->first();
    $balance->usd += 100;
    $balance->save();

    // A LOT MORE LOGIC HERE

    $balance = UserBalance::where('user_id', 7)
                    ->lockForUpdate()
                    ->first();
    $balance->usd -= 100;
    $balance->save();

} catch (\Exception $e) {
    DB::rollback();
    return json_encode ([
        'success' => false,
        'message' => 'error',
    ]);
}
DB::commit();

一切正常,我在提交之前尝试了一些“睡眠(20)”并发送了另一个申请(没有睡眠)并且该行确实被锁定,但我们面临一个问题。当我们从 cron 多次运行它时,似乎该函数运行在完全相同的毫秒上,然后锁似乎不起作用,这可能吗?除了使用队列之外,还有其他解决方案吗?

CRON 只是像这样多次调用路由:

* * * * * curl http://test.com.br/test
* * * * * curl http://test.com.br/test
* * * * * curl http://test.com.br/test

标签: mysqllaravellaravel-5transactionspessimistic-locking

解决方案


我不明白为什么你需要DB::transcation在这里使用 a ,因为这个操作是一个原子操作。

你可以简单地做一个UserBalance::where('user_id', 2)->increment('usd', 100).

这将向后端发送一个查询,将值递增usd100。


推荐阅读