首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Increment、Decrement以及Model::decrement()和Model::increment()在Laravel中无法很好地工作

Increment、Decrement以及Model::decrement()和Model::increment()在Laravel中无法很好地工作
EN

Stack Overflow用户
提问于 2020-09-29 18:28:09
回答 1查看 82关注 0票数 1

好吧,我有个奇怪的问题。我正在通过POST方法从API接收数据。当请求到达预定的路由时,我从请求中获取数据,然后根据请求类型减少或增加用户余额。

我们有两种请求类型:贷记和借记。对于借方,我会减少用户余额,对于贷方,我会将用户余额增加请求中的金额。

现在的问题是,这对几乎99%的请求都有效,但是对于一些请求,余额并没有减少,尽管它是接收到的。

下面的图片就是我所说的一个例子。带绿色边框的记录是按要求工作的记录,其中金额按要求递减。红色边框的那个是它无法减少的地方,即使它记录了数量。下面也是我用来做这件事的代码。

请帮助我知道问题可能在我的代码中的哪里,或者如何解决,以便结果一致。我使用的是普通的递减和递增运算符,但它的工作方式是相同的。我决定尝试一下laravel Model::decrement()Model::increment(),但是我遇到了同样的错误!

代码语言:javascript
复制
public function Debit(){
     $data = json_decode(file_get_contents('php://input'), true);
     $username = $data['Login'];
     $user = User::where('username', $username)->first();
     if(!$user){
       $rivalaoResponse = ["d"=>["ErrorCode"=>-10,"HasErrors"=>true,"Message"=>"InvalidPlayer"]];
       return response()->json($rivalaoResponse);
     }
     $type="debit";
     $userId = $user->id;
     $amount = $data['Amount'];
     $gameId = $data['GameId'];
     $roundId = $data['RoundId'];
     $sequence = $data['Sequence'];
     if($user->decrement('casino_bakiye', $amount)){
       $updatedBalance= $user->refresh()->casino_bakiye;
     if($sequence){
       $game = XpgTransaction::where('gameId', $gameId)
                             ->where('roundId', $roundId)
                             ->where('sequence', $sequence)
                             ->first();
       if(!$game){
         $trxn = new XpgTransaction;
         $trxn->user_id = $userId;
         $trxn ->request=json_encode($data);
         $trxn->type =$type;
         $trxn->casino_balance = (float)$updatedBalance;
         $rivalaoResponse = ["d"=>["Data"=>[(float)$updatedBalance],"ErrorCode"=>0,"HasErrors"=>false,"Message"=>""]];
         
         try {
           return  response()->json($rivalaoResponse);
            } finally {
           $trxn->save();
       }
        
       }
       $rivalaoResponse = ["d"=>["ErrorCode"=>-20,"HasErrors"=>true,"Message"=>"Duplicate transaction"]];
       return response()->json($rivalaoResponse);
     }
     }
     

   }

Database illustration

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-10-07 10:01:01

嗯,你正在经历所谓的Race Condition,这是一种情况,你正在进行各种事务,同时更新不同的表。在这样做的时候,一些事务可能会在其他事务之前运行,从而导致问题。要解决这个问题,您可以做两件事,首先,使用Laravel Transactions这是您将所有操作放在事务中,然后在完成所有操作后,提交DB。在这种情况下,我建议将事务与pessimistic locking一起使用,在这种情况下,当一个请求正在处理时,您可以锁定表,这样其他请求就不会从表中读取数据,等等。您可以在这里阅读有关pessimistic locking的更多信息:Laravel's Pessimistic Locking,在这里您可以找到有关Laravel TransactionsDB: Transactions in Laravel的更多信息

代码语言:javascript
复制
...
DB::beginTransaction();
$user = User::where('username', $username)->sharedLock()->first();
...
$game = XpgTransaction::where('gameId', $gameId)
                             ->where('roundId', $roundId)
                             ->where('sequence', $sequence)
                             ->sharedLock()->first();
...
 $trxn->save();
DB::commit()
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/64117740

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档