PHP / MySQL中的竞争条件问题

时间:2015-07-21 08:16:50

标签: php mysql race-condition

我写了一个bash脚本,尝试向我的网站发送一些POST请求。在我网站上的POST请求处理程序中,我有一个逻辑:

$std = new \stdClass();
$std->ok = false;
$order = getOrderById(id); // table: orders
$user_id = user_id;
if (!empty($order)) {
    if (!orderIsntPerformedByUser($user_id, $order->id)) { // table: performed_orders
        updateUserData($user_id, ['user_balance', 'user_balance+1']); // table: users
        performOrderByUserId($order->id, $user_id); // table: performed_orders
    }
}
echo json_encode((array)$std);
return;

bash脚本:

for i in {1..5}
do
    curl 'http://example.com/handlePostRequest' --form-data="id=1" &
done

它在后台发送5个帖子请求,我的网站立即响应。所有请求同时执行,一些请求从服务器收到“真实”响应。

我认为我需要使用事务机制来避免这种情况?或者如何在用户请求之间做一些延迟以避免它?什么是解决它的最佳方法?我试图对类似的网站采取这种行动,我的请求之间有延迟。

非常感谢你,抱歉我的英语不好。

1 个答案:

答案 0 :(得分:3)

我会扩展我的评论。你在服务器上做错了。您正在使用PHP来验证订单是否在数据库中,但PHP脚本不是数据权限 - MySQL是。 MySQL的工作是处理数据。您的要求是您插入表格,如果记录与order_id一起存在 - 请更新current_balance

这是通过在unique key上放置order_id来实现的。然后您的查询如下所示:

INSERT INTO orders (order_id, current_balance) VALUES (1, 13.37) ON DUPLICATE KEY UPDATE current_balance = current_balance + 333.333

这种方法的好处:

  • 数据库处理数据(这是它的工作)
  • 不会发生并发问题
  • 保留数据完整性
  • 您需要较少的代码来处理