此 PostgreSQL 代码会造成哪些并发问题?

What concurrency issues can this PostgreSQL code create?

好的,这是不言自明的模式:

STORE(storeID, name, city)
PRODUCT(productID, name, brand)
PRODUCT_FOR_SALE(productID, storeID, price)

我有 2 笔交易:T1 和 T2
T1 将 'London' 的任何商店中销售的任何产品的价格提高 5%。
T2 将成本 >= 1050 美元的任何产品的价格降低 10%

我被问到的是告诉我他们可能导致什么样的并发异常,以及我应该申请什么隔离级别哪个交易让它安全。

没有给出交易代码,但我想应该是这样的:

# T1:
BEGIN;
    UPDATE product_for_sale 
    SET    price = price + ((price/100) *5)
    WHERE  storeID IN (SELECT storeID FROM store WHERE city='London')
COMMIT;

# T2:
BEGIN;
    UPDATE product_for_sale
    SET    price = price - (price/10)
    WHERE  price >= 1050
COMMIT;

我的 "guess" 到 READ COMMITTED(默认)可能发生的情况是:
考虑一个产品 P,在 'London' 以 1049 美元

的价格售出

如果我没有弄乱定义,应该是幻读的情况,如果我将 T2 设置为 ISOLATION LEVEL REPEATABLE READ

,这将得到修复

首先,您对并发问题的含义不是很清楚。可能是:

  1. 可能是个问题,但由 PostgreSQL 自动处理,因此不会出现问题。

  2. 可能会产生意外错误或不良结果的东西。

对于 1.,这是由序列化试图同时修改相同行的事务的锁处理的。

我猜你对 2 更感兴趣。

你描述的情况可能会发生,但这不是并发问题。这只是意味着 T1 逻辑上 发生在 T2 之前。这将适用于所有隔离级别。

我可能遗漏了一些东西,但我在这里看到的唯一潜在问题是两个语句之间的死锁:

它们都可以更新多行,因此可能会发生其中一个先更新行 X,然后尝试更新行 Y,而该行已被另一个语句更新。第一个语句然后被阻止。现在第二条语句想要更新 Y 行也被阻塞了。

这样的死锁在一秒后被死锁解决程序打破,方法是杀死其中一个有错误的语句。

请注意,死锁也不是真正的问题,您的代码所要做的就是重复失败的事务。