postgresql Postgres合并无提示忽略唯一约束冲突

bkhjykvo  于 2023-11-18  发布在  PostgreSQL
关注(0)|答案(1)|浏览(189)

以下引用来自这里: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功能的一个有价值的补充,因为肯定会有用户(我现在)不希望他们的整个合并插入(或更新)失败,仅仅因为一行或几行有唯一约束违反。

mefy6pfw

mefy6pfw1#

我确实使用下面的代码运行了一些测试,正如预期的那样,我发现,如果在插入merge命令期间发生了一个唯一的违规异常,这个唯一的违规异常就会冒泡,并导致整个merge查询失败。
这意味着,例如,如果您正在执行一个长时间运行的批处理merge操作,merge可能会执行99%的工作,但如果最后一个插入行导致唯一的违规异常,整个merge查询就会回滚,所有工作都会丢失。
在许多可预见的merge用例中,我预计这会非常令人失望,远远达不到理想的效果。在我看来,merge提供忽略导致唯一违规异常的行的能力,而不是tank整个查询,会更好。
我认为这个附加功能(在插入查询过程中忽略导致唯一冲突异常的行)应该被添加到sql标准和postgres中。

测试代码

在一个SQL进程中运行以下内容:

create table tmp_table (col int);

insert into tmp_table (col)
select *
from generate_series(1, 10000000) as s(i);

CREATE TABLE tmp_table2 (col int unique);

merge into tmp_table2 tt2
using (
  select *
  from tmp_table
) as tt1
on tt2.col = tt1.col
when matched then do nothing
when not matched then
  insert (col)
  values (tt1.col);

字符串
在第二个sql进程中,在第一个sql进程中运行merge命令后立即运行以下命令:

insert into tmp_table2 (col)
values (9000000);

相关问题