带有版本控制的竞争条件

问题描述 投票:0回答:1

在我使用 Postgresql 的应用程序中,订购产品过程可能会导致竞争条件。让我描述一下我的案例。我的数据库中有三个表:

  • 第一个是产品表:
Id string
Quantity int
  • 用户
Id string
Name string
  • 订购
Id string
UserId string
ProductId string
Quantity int

在这个过程中,我分两个阶段来完成。我从产品表中读取以检查“产品是否可用”如果房间不可用,我会向用户回复一条错误消息;另一方面,我会为订购表创建一条记录,并向用户发送一条响应成功消息。

这是处理该问题的sql:

--- get quantity from product id
SELECT quantity
FROM Product
WHERE id = '456';

--- if the product's quantity is greater than the ordering quantity then
UPDATE Product
SET quantity = quantity - 1
WHERE id = '456';

INSERT INTO Ordering (id, user_id, product_id, quantity)
VALUES ('1', '123', '456', 1);

--- else I would respond to customer error response

但是我意识到这个过程可能会导致竞争条件。然后我找到了一个想法来解决它。我在产品和订购表中创建了一个名为 version 的字段。我在检查可用产品时更新版本。但我对这个解决方案有疑问。

SQL 将变为如下:

--- get quantity from product id
SELECT quantity
FROM Product
WHERE id = '456' and version = 1;

--- if the product's quantity is greater than the ordering quantity then
UPDATE Product
SET quantity = quantity - 1, version = version + 1
WHERE id = '456' and version = 1;

INSERT INTO Ordering (id, user_id, product_id, quantity, version)
VALUES ('1', '123', '456', 1, 1);

--- else I would respond to the customer error response

如果产品的数量是99,并且我同时有100个客户购买产品的请求。在这种情况下,只有一位客户订购成功,另一位客户订购失败。但我预计有 99 人下单成功,只有 1 名客户下单失败。

有人可以给我一些关于这个问题的建议吗?我花了很长时间来考虑。感谢您的关注。

postgresql race-condition
1个回答
0
投票

您面临的问题确实是数据库中竞争条件的典型示例。在您的场景中,多个请求尝试同时更新产品数量,这可能会导致意外结果。使用版本字段来处理并发控制是朝着正确方向迈出的一步,但似乎并不能完全解决问题。

为了更有效地处理这种情况,您可以使用一个称为“乐观并发控制”的概念。以下是实施方法:

  1. 向您的产品表添加版本列:

    ALTER TABLE Product
    ADD COLUMN version integer DEFAULT 0;
    
  2. 修改您的 SQL 查询:

    -- get quantity and version from product id
    SELECT quantity, version
    FROM Product
    WHERE id = '456';
    
    -- if the product's quantity is greater than the ordering quantity and version matches
    UPDATE Product
    SET quantity = quantity - 1, version = version + 1
    WHERE id = '456' AND version = 1;
    
    -- Check the number of rows affected by the update query.
    -- If it's 0, then the version mismatch occurred, and the operation should be rolled back.
    -- If it's 1, the update was successful.
    -- Handle this logic in your application code.
    
    -- If the update was successful, insert into Ordering table.
    
  3. 处理应用程序代码中的并发冲突: 在您的应用程序中,执行更新查询后,检查有多少行受到影响。如果更新影响了 0 行,则意味着自您上次读取该行以来,另一个事务已经更新了该行。在这种情况下,您可以通过重试整个过程或通知用户该产品不再可用来处理冲突。

通过实施乐观并发控制,您可以允许多个事务独立进行,除非存在冲突(即并发修改相同数据)。当发生冲突时,您的应用程序可以检测到并进行适当处理,确保您的订购过程既安全又高效。

© www.soinside.com 2019 - 2024. All rights reserved.