INSERT-SELECT查询是否可以受竞争条件的影响?

Lor*_*igs 6 sql postgresql race-condition

我有这个查询,balances如果表中不存在相应的行,则尝试向表中添加行totals.使用PostgreSQL上的默认隔离级别在事务中运行查询.

INSERT INTO balances (account_id, currency, amount)
SELECT t.account_id, t.currency, 0
FROM balances AS b
RIGHT OUTER JOIN totals USING (account_id, currency) AS t
WHERE b.id IS NULL
Run Code Online (Sandbox Code Playgroud)

我有一个UNIQUE约束balances (accountId, currency).我担心如果多个会话同时执行此查询,我将陷入竞争状态,导致重复键错误.我已经看过很多关于这个问题的问题,但它们似乎都涉及子查询,多个查询或pgSQL函数.

由于我没有在我的查询中使用任何这些,它是否没有竞争条件?如果不是我该如何解决?

Clo*_*eto 3

是的,它会因duplicate key value violates unique constraint错误而失败。我所做的是将插入代码放在一个try/except块中,当抛出异常时,我捕获它并重试。就这么简单。除非该应用程序拥有大量用户,否则它将完美运行。

在您的查询中,默认隔离级别就足够了,因为它是单个插入语句,并且不存在幻读的风险。

请注意,即使将隔离级别设置为可序列化,try/ except 块也是无法避免的。来自关于可序列化的手册:

与可重复读取级别一样,使用此级别的应用程序必须准备好因序列化失败而重试事务