Php 如何检查一个条件,如果它是真的,然后在比赛条件下插入一些东西

Php 如何检查一个条件,如果它是真的,然后在比赛条件下插入一些东西,php,mysql,laravel,mariadb,Php,Mysql,Laravel,Mariadb,我们有一个api函数,它用一个select查询检查数据库的条件,如果它是真的,我们只想一次向数据库插入一些东西,例如插入到数据库,插入完成了。问题是,当我们多次调用这个api函数时,并发的竞争条件会发生,换句话说,假设我们调用这个函数2次,第一次请求检查条件是否为真,然后第二次请求检查条件是否为真,然后再次检查它是否为真,这样它们就可以插入到数据库中。但我们想知道,当我们检查条件时,在我们插入之前,没有其他人可以再次检查它 我们使用php/Laravel并了解一些方法,比如使用insert-in

我们有一个api函数,它用一个select查询检查数据库的条件,如果它是真的,我们只想一次向数据库插入一些东西,例如插入到数据库,插入完成了。问题是,当我们多次调用这个api函数时,并发的竞争条件会发生,换句话说,假设我们调用这个函数2次,第一次请求检查条件是否为真,然后第二次请求检查条件是否为真,然后再次检查它是否为真,这样它们就可以插入到数据库中。但我们想知道,当我们检查条件时,在我们插入之前,没有其他人可以再次检查它

我们使用php/Laravel并了解一些方法,比如使用
insert-into。。。选择
或使用类似于替换为…之类的方法

$order = Order::find($orderId);
$logRefer = $order->user->logrefer;
if (!is_null($logRefer) && is_null($logRefer->user_turnover_id)) {
     $userTurnover = new UserTurnover();
     $userTurnover->user_id = $logRefer->referrer_id;
     $userTurnover->order_id = $order->id;
     $userTurnover->save();

     $logRefer->order_id = $order->id;
     $logRefer->user_turnover_id = $userTurnover->id;
     $logRefer->save();
}

如果
logrefere
未找到,只需设置一次它和相应的
用户营业额。我们希望只看到一个与此订单相关的
用户营业额
,但同时运行多次后,我们会看到多个
用户营业额
已插入。

我通常在需要顺序操作时利用事务,但我认为在您的情况下,由于以下事实,情况有点复杂:如果函数正在运行,则还需要有条件地计算条件。所以我给你的想法是在数据库中有一个变量(另一个表)用作信号量,它允许或不允许在表上执行操作(由设置或取消设置信号量值的事实给出的条件)。作为一名优秀的程序员,我认为信号量在很多并发函数的情况下都很有用。

数据库应该在预期是唯一的列上有一个唯一的键,即使代码中的某些机制可以防止重复

将连接的查询包装到事务中,该事务将在竞争事件条件下失败并回滚

try {
    DB::transaction(function() {
        $order = Order::find($orderId);
        ...
        $logRefer->save();
    });
} catch (\Illuminate\Database\QueryException $ex) {
    Log::error(“failed to write to database”);
}

防止争用条件(本例中为重复数据)的唯一安全方法是在表中添加一些(mullticolumn)唯一键。这不是任何php方法吗?“不是任何php方法吗?”我认为Laravel也有一些锁定方法,但数据库可以做得更好。你能告诉我们更多关于如何在另一个表上使用变量实现信号量的信息吗?简单我们有一个表(我们仅用于此目的,所以它只包含一行):sem_user(val varchar(1))是我们可以设置val的地方(例如设置为“S”)当我们需要锁定代码或取消设置val(null)时,如果操作已完成并且可以执行新操作。确保在事务中快速设置/取消设置val,或者创建一个函数SetUnsetSemaphore(),这将为您完成这项工作。创建另一个读取val当前状态的函数LoadValSemphoreUser(),这样基本上就可以将代码封装到这个逻辑流中:1-SetUnsetSemaphore();2-if(LoadValSemphoreUser()=null){//您的代码…}3-SetUnsetSempahore();很明显,这不是exat代码,这只是为了让你明白我的意思。没错,但这将解决我目前的问题。我正在寻找一种方法来解决像这样更复杂的问题