【问题标题】:Increment, Decrement, as well as Model::decrement() and Model::increment() not working well in LaravelIncrement、Decrement 以及 Model::decrement() 和 Model::increment() 在 Laravel 中无法正常工作
【发布时间】:2021-01-14 22:54:42
【问题描述】:

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

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

现在的问题是,这几乎适用于 99% 的请求,但对于某些请求,尽管已收到余额,但余额并未减少。

下图是我所说的一个例子。带有绿色边框的记录是按要求工作的记录,其中金额按要求递减。带有红色边框的那个是即使它记录了金额也没有减少的地方。下面也是我用来执行此操作的代码。

请帮助我了解我的代码中可能出现的问题或如何解决问题,以使结果保持一致。我使用的是正常的递减和递增运算符,但它的工作方式相同。我决定尝试 laravel Model::decrement()Model::increment() 但我遇到了同样的错误!

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

【问题讨论】:

  • 这行我看不懂if($user->decrement('casino_bakiye', $amount))
  • 也就是说,如果用户余额减少,那么该代码将运行@sta

标签: php laravel


【解决方案1】:

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

...
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()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-01-07
    • 2015-03-27
    • 1970-01-01
    • 2013-07-23
    • 2013-02-18
    • 2016-02-07
    相关资源
    最近更新 更多