【发布时间】:2019-11-06 05:54:41
【问题描述】:
我们有一个 api 函数,它使用选择查询检查数据库的条件,然后如果它是真的,我们只想一次向数据库插入一些东西,例如插入到数据库中插入完成。问题是当我们多次调用此 api 函数时同时发生竞争条件,换句话说,假设我们调用此函数 2 次,第一次请求检查条件是否为真,然后第二次请求检查该条件是否为真,因此它们确实插入数据库。但是我们希望当我们检查条件时,在我们插入之前没有其他人可以再次检查它。
我们使用 php/Laravel 并且知道一些方法,例如使用 insert into ... select 或使用诸如 replace 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();
}
如果logrefer 未找到,则设置它并对应user-turnover 一次。我们预计只会看到一个与此订单相关的 user-turnover,但在同时运行多次后,我们看到多个 user-turnover 已插入。
【问题讨论】:
-
防止竞争条件(本例中为重复数据)的唯一安全方法是在表中添加一些(多列)UNIQUE 键。
-
是不是什么php方式?
-
"难道不是任何 php 方式吗?" 我认为 Laravel 也有一些锁定方法,但数据库可以做得更好。