postgresql 具有版本控制的竞争条件

1qczuiv0  于 2023-11-18  发布在  PostgreSQL
关注(0)|答案(1)|浏览(150)

在我使用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


然而,我意识到这个过程可能会导致竞争条件。然后我找到了一个解决方案。我在Product and Ordering表中创建了一个名为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人订购成功,只有一个客户失败。
关于这个问题,谁能给予我一些建议?我考虑了很久,谢谢你的关注。

sigwle7e

sigwle7e1#

尝试以下操作。不测试可用数量,而是让数据库自动检查它。设置一个检查约束,指定结果数量不得小于0。

alter table products
      add constraint positive_quantity check (quantity >= 0);

字符串
现在,当您更新数量时,Postgres将确保结果数量为0或更大(参见demo)。如果是,则执行更新,并锁定该行以防止进一步更新(它仍然可以阅读,并获取更新前的值)直到提交。后续的更新将从更新的值开始执行相同的检查。如果结果数量小于0,则异常。您需要处理异常而不发出插入。
注意:只需确保products表更新和orders表插入在同一个事务中。

相关问题