1

我的表中有一些重复的行,但无法通过 http 请求插入,因为我对用户余额进行了验证,每个请求都会更改,并且管理员必须在另一个请求之前接受一个请求。在这种情况下,用户的余额为 1000 美元。根据我的代码,他可以请求一次 1000 美元。但突然之间,我的数据库中同时有两行。它是如何发生的,这个问题的解决方案是什么?

我假设当第一个请求到达时,withdraw表由于其他一些计算而被锁定,因此余额不变并且查询排队,因为用户由于表锁定而没有得到响应,他再次请求然后插入了两个请求!

请注意,这种情况并非每天都在发生。这种情况很少发生,例如一年中的 1 或 2 个重复请求

    public function withdrawBalance(Request $request)
    {
        if ($request->api_key == ApiKey()) {

            $userInfo = User::find($request->user_id);

            $checkPendingRequest = Withdraw::where(['user_id' => $request->user_id, 'status' => 0])->get(); //status column have default 0 until admin approval

            if (count($checkPendingRequest) > 0) {
                return response()->json(['status' => false, 'action' => 'already_pending_one', 'message' => 'Already have a pending request!.']);
            }

            $gs = GeneralSetting::first();
            $balance = HoldingBalance($request->user_id)['withdrawble_balance'];


            if ($request->amount > $balance) {
                return response()->json(['status' => false, 'action' => 'insufficiant_balance', 'message' => 'Insufficient amount!.']);
            }


            if ($request->withdraw_method == 'bkash') {
                $method_name = 'Digital';
            } else {
                $method_name = $request->withdraw_method;
            }

            Withdraw::create([
                'branch_id' => $request->branch_id ?? 1,
                'user_id' => $userInfo->id ?? null,
                'purpose' => "$method_name Withdraw",
                'withdraw_method' => $request->withdraw_method ?? null,
                'withdraw_account' => $request->withdraw_account ?? null,
                'amount' => round($request->amount, 2),
                'payble_amount' => $request->amount,
                'status' => 0
            ]);
            
            return response()->json(['status' => true, 'action' => 'success', 'message' => 'Successfully submitted withdrawn request!.']);
            
        } else {
            return "Access Denied";
        }
    }
4

1 回答 1

0

我猜任何用户都双击“提交”所以 2 个收据请求到达,每个都执行了代码级别检查,没有看到执行另一个查询

我还没有看到使用表锁或事务

DB::beginTransaction();
check_if_data_already_exist();
add_data();
DB::commit();

此解决方案将大大降低系统的性能。

最简单的解决方案是每个用户在给定时刻发送一个请求的选项。

这个问题有很多实现。为了提供可能的解决方案,我们需要获取更多信息:是否可以使用会话?队列可以用来输入查询吗?也许每个用户在数据库中都包含一行,您可以简单地在数据库级别创建一个唯一键

于 2020-12-27T10:35:19.443 回答