为什么即使对象创建失败,Postgres 序列项也会上升?

TJB*_*TJB 5 postgresql database-sequence

我有一个 Postgres 项目,其中我的模型之一是Client,只需通过其主键进行索引。我在创建客户端时遇到了问题,因为有人创建了一个客户端,同时显式设置了我读过的主键,这不会影响 Postgres 的客户端序列表,该序列表负责在任何时候自动递增主键 1创建了一个 Client 对象。

我运行了一些 SQL 查询来研究它,发现当前序列值实际上比数据库中客户端的最高 ID 263 低 1,即 262,因此表明 ID 为 263 的客户端已经存在。我尝试在前端应用程序中创建一个客户端,再次收到错误,并决定重新运行查询。我看到数据库中没有像预期的那样创建新客户端,但我也注意到序列值确实达到了 263,因此当我尝试再次创建客户端时,它起作用了!

即使相关模型的创建失败,PostgreSQL 序列表也会递增,这是正常行为吗?如果是这样,这似乎可能会导致一些严重的问题。

fre*_*ish 8

是的,这是预期的行为。请参阅文档

下一个值

将序列对象前进到其下一个值并返回该值。这是以原子方式完成的:即使多个会话同时执行 nextval,每个会话也将安全地接收一个不同的序列值。

如果使用默认参数创建了序列对象,则连续的 nextval 调用将返回从 1 开始的连续值。可以通过在 CREATE SEQUENCE 命令中使用特殊参数来获得其他行为;有关详细信息,请参阅其命令参考页。

重要提示:为了避免阻塞从同一序列获取数字的并发事务,nextval 操作永远不会回滚;也就是说,一旦获取了某个值,即使稍后执行 nextval 的事务中止,该值也被视为已使用。这意味着中止的事务可能会在分配值的序列中留下未使用的“漏洞”。

请注意,nextval通常设置为自动增量/串行列的默认值。

nextval还请尝试想象一下,如果回滚,会有多困难和低效。本质上,您必须锁定每个客户端,nextval直到处理整个事务(获取锁定的事务)。在这种情况下,请忘记并发插入。

如果是这样,这似乎可能会导致一些严重的问题。

像什么?您的情况的问题是有人手动指定自动增量列的值。除非你是武士,否则你永远不应该这样做。:)