首页 > 解决方案 > 约束使插入失败,但主键仍然递增

问题描述

我有一个表,它有一个基于序列的主键START WITH 1 INCREMENT BY 1

主键效果很好,可以根据需要递增。

但是我有另一个字段是唯一的。当我尝试插入无法通过 UNIQUE 检查的新行时,主键仍会更新。我希望这不会更新主键,因为 INSERT 失败。

为了测试这一点,我插入了两行,主键分别是 1 和 2。然后我尝试再次插入第二行的数据。由于唯一约束,它失败了。然后我插入了另一行具有唯一值的行,主键从 2 跳到 4,跳过了在唯一约束没有失败的情况下将使用的三个。

这是 Postgres 的预期行为吗?

标签: postgresql

解决方案


那是正常的行为。

该文档解释说:

为了避免阻塞从同一序列中获取数字的并发事务,nextval 操作永远不会回滚;也就是说,一旦获取了一个值,它就被认为是已使用的,并且不会再次返回。即使周围的事务稍后中止,或者调用查询最终没有使用该值也是如此。例如,一个INSERTwithON CONFLICT子句将计算要插入的元组,包括执行任何必需的nextval调用,然后再检测任何可能导致它遵循ON CONFLICT规则的冲突。这种情况会在赋值序列中留下未使用的“漏洞”。因此,PostgreSQL 序列对象不能用于获取“无间隙”序列

有关详细信息和示例,您可以阅读我的博客


推荐阅读