在我使用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人订购成功,只有一个客户失败。
关于这个问题,谁能给予我一些建议?我考虑了很久,谢谢你的关注。
1条答案
按热度按时间sigwle7e1#
尝试以下操作。不测试可用数量,而是让数据库自动检查它。设置一个检查约束,指定结果数量不得小于0。
字符串
现在,当您更新数量时,Postgres将确保结果数量为0或更大(参见demo)。如果是,则执行更新,并锁定该行以防止进一步更新(它仍然可以阅读,并获取更新前的值)直到提交。后续的更新将从更新的值开始执行相同的检查。如果结果数量小于0,则异常。您需要处理异常而不发出插入。
注意:只需确保
products
表更新和orders
表插入在同一个事务中。