好吧,我有个奇怪的问题。我正在通过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);
}
}
}发布于 2020-10-07 10:01:01
嗯,你正在经历所谓的Race Condition,这是一种情况,你正在进行各种事务,同时更新不同的表。在这样做的时候,一些事务可能会在其他事务之前运行,从而导致问题。要解决这个问题,您可以做两件事,首先,使用Laravel Transactions这是您将所有操作放在事务中,然后在完成所有操作后,提交DB。在这种情况下,我建议将事务与pessimistic locking一起使用,在这种情况下,当一个请求正在处理时,您可以锁定表,这样其他请求就不会从表中读取数据,等等。您可以在这里阅读有关pessimistic locking的更多信息:Laravel's Pessimistic Locking,在这里您可以找到有关Laravel TransactionsDB: 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()https://stackoverflow.com/questions/64117740
复制相似问题