这个查询能保证我的'无竞赛'PK值吗?

时间:2009-10-21 05:41:02

标签: sql mysql

我刚刚阅读How to avoid a database race condition when manually incrementing PK of new row.

有很多好的建议,比如有一个单独的表来获取PK值。

所以我想知道是否有这样的查询:

INSERT INTO Party VALUES(
    (SELECT MAX(id)+1 FROM 
        (SELECT id FROM Party) as x),
'A-XXXXXXXX-X','Joseph')

可以避免竞争条件吗?

整个声明是否保证是原子的?是不是在mysql中?的PostgreSQL?

3 个答案:

答案 0 :(得分:4)

在关系数据库中创建主键时避免竞争条件的最佳方法是允许数据库生成主键。

答案 1 :(得分:2)

它适用于使用表级锁定(MyISAM)的表,但在Innodb等上,它可能会死锁或产生重复键,我认为,这取决于使用的隔离级别。

在任何情况下这样做都是一个非常糟糕的主意,因为它在一般情况下不能很好地工作,但在低并发性测试期间似乎可行。这是一个麻烦的方法。

最好使用另一个表并在那里递增一个值;这更有可能是无竞赛/无死锁。

答案 2 :(得分:0)

不,你仍然有问题,因为如果两个查询同时尝试增加内部选择的情况,则会处理另一个查询。

您最好的选择,如果您想要保证,如果您不希望数据库这样做,那就是在那里有一个唯一的密钥。

如果插入时出错,请再次尝试查询,一旦主键唯一,它就会起作用。

在这种情况下,最好的办法是首先只插入id和任何其他非空列,然后进行更新以将可空列设置为正确的列。