2012-11-28 35 views
2

假设我们有一个t1表,其中整数weight列被标记为唯一,item_id是主键。以下查询可以失败吗?这个查询竞赛条件是免费的吗?

UPDATE t1 
    SET weight = SELECT new_weight FROM (
    SELECT MAX(weight) + 1 AS new_weight FROM t1 
) qs 
WHERE item_id = ? 

其中?是一个参数。有可能是因为一场比赛两项物品会试图设定相同的重量?或者那个数据库引擎是特定的?

+0

这取决于数据库引擎以及正在使用的隔离级别(如果适用)。 –

+0

如果您的数据库管理系统支持序列,自动编号或标识列,则应该使用它们。否则,您为多个用户唯一安全的选择就是序列化对表的访问权限,即为您的交易锁定表。 –

回答

2

是的,你可以得到两个相同的重量值由于竞争条件。切换到ISOLATION LEVEL SERIALIZABLE以避免这种情况(您可能会遇到一个死锁,而您可以重试,但您可以避免任何数据损坏)。或者采用RDBMS特有的适当的悲观锁定。

+0

击败我11秒:) – ppeterka

0

如果两个事务并行执行,这是可能的。

这两个事务都会得到相同的值MAX(weight)+1,然后尝试使用相同的值进行更新,从而导致违反约束。