我感兴趣,避免这个小问题的最佳做法是什么:)
让我们看两个客户端,两者都试图在表中插入具有唯一约束的行 假设它是“url”列。
有一次可能出现以下情况:
1)客户A看起来,表中是否有“a”字样
2)客户A得到答案,没有那个网址
3)客户A将插入URL“a”
4)客户B看起来,表中是否有“a”字样
5)客户B得到答案,没有那个网址
6)客户端A插入URL“a”
7)客户端B将插入URL“a”,但会出现重复的密钥错误
我理解正确,避免它的最佳方法 - 只是在应用程序级别重试?
答案 0 :(得分:2)
您可以通过在事务开始时取出显式锁来避免错误,但这可能对并发性和吞吐量不利。
http://www.postgresql.org/docs/current/interactive/explicit-locking.html
如果您不阻止并发尝试,则需要以某种方式处理重试。您可以将其封装在一个函数中,而不是将该逻辑放在应用程序代码中。逻辑类似于merge_db()示例:
答案 1 :(得分:1)
如果您在SERIALIZABLE隔离级别运行,客户端B将被强制等待A的事务完成,然后返回url的值。由于此值尚不存在,因此您无法锁定记录(没有记录),因此将使用索引上的间隙锁定。但正如@kgrittn所提到的,这会对性能和并发性产生负面影响。因此,最好处理重复键错误