以下引用来自这里:https://pganalyze.com/blog/5mins-postgres-15-merge-vs-insert-on-conflict
他的评论基本上是MERGE处理并发性的缺点是,当你并发地执行并发性时,在你执行MERGE语句的同时,还有另一个并发性正在进行,那么MERGE可能不会注意到这一点。MERGE会进入它的并发性逻辑,然后它会得到一个唯一的违规。
我记得,当他最初设计的MVCC CONFLICT功能,因为这个约束如何在Postgres中工作,你不能实现MERGE与它的一般语法和选项以同样可靠的方式工作。如果你想要MERGE的通用性,你必须接受这样的事实,你可能会得到唯一的约束违反,当有并发插入,而不是与MVCC CONFLICT,它的设计方式与其推测性插入,保证你要么得到一个rewrite要么得到一个UPDATE,这是真的,即使有并发插入。如果你需要保证,你可能想选择rewrite ON CONFLICT。
假设我们正在做一个非常大的merge
,这将花费很长时间,在合并过程中,发生了上面引用中描述的并发插入,导致插入逻辑期间的唯一约束违反。在这种情况下到底发生了什么?它会导致整个merge
查询失败并抛出唯一约束异常吗?
或者,如果在最后的插入逻辑中,一行或多行确实发生了唯一约束冲突,那么只有那些有唯一约束冲突的行被忽略,而插入的其余部分照常进行?
我认为postgres的merge
功能不支持这个(后者--默默地忽略唯一约束违反),但我确实认为这将是对merge
功能的一个有价值的补充,因为肯定会有用户(我现在)不希望他们的整个合并插入(或更新)失败,仅仅因为一行或几行有唯一约束违反。
1条答案
按热度按时间mefy6pfw1#
我确实使用下面的代码运行了一些测试,正如预期的那样,我发现,如果在插入
merge
命令期间发生了一个唯一的违规异常,这个唯一的违规异常就会冒泡,并导致整个merge
查询失败。这意味着,例如,如果您正在执行一个长时间运行的批处理
merge
操作,merge
可能会执行99%的工作,但如果最后一个插入行导致唯一的违规异常,整个merge
查询就会回滚,所有工作都会丢失。在许多可预见的
merge
用例中,我预计这会非常令人失望,远远达不到理想的效果。在我看来,merge
提供忽略导致唯一违规异常的行的能力,而不是tank整个查询,会更好。我认为这个附加功能(在插入查询过程中忽略导致唯一冲突异常的行)应该被添加到sql标准和postgres中。
测试代码
在一个SQL进程中运行以下内容:
字符串
在第二个sql进程中,在第一个sql进程中运行
merge
命令后立即运行以下命令:型