PostgreSQL:2+个客户,唯一约束 - >竞争条件

时间:2012-05-04 11:21:34

标签: postgresql unique race-condition

我感兴趣,避免这个小问题的最佳做法是什么:)

让我们看两个客户端,两者都试图在表中插入具有唯一约束的行 假设它是“url”列。

有一次可能出现以下情况:
1)客户A看起来,表中是否有“a”字样 2)客户A得到答案,没有那个网址 3)客户A将插入URL“a”
4)客户B看起来,表中是否有“a”字样 5)客户B得到答案,没有那个网址 6)客户端A插入URL“a”
7)客户端B将插入URL“a”,但会出现重复的密钥错误

我理解正确,避免它的最佳方法 - 只是在应用程序级别重试?

2 个答案:

答案 0 :(得分:2)

您可以通过在事务开始时取出显式锁来避免错误,但这可能对并发性和吞吐量不利。

http://www.postgresql.org/docs/current/interactive/explicit-locking.html

如果您不阻止并发尝试,则需要以某种方式处理重试。您可以将其封装在一个函数中,而不是将该逻辑放在应用程序代码中。逻辑类似于merge_db()示例:

http://www.postgresql.org/docs/current/interactive/plpgsql-control-structures.html#PLPGSQL-ERROR-TRAPPING

答案 1 :(得分:1)

如果您在SERIALIZABLE隔离级别运行,客户端B将被强制等待A的事务完成,然后返回url的值。由于此值尚不存在,因此您无法锁定记录(没有记录),因此将使用索引上的间隙锁定。但正如@kgrittn所提到的,这会对性能和并发性产生负面影响。因此,最好处理重复键错误