使用该select max(id) + 1
方法,同时插入的两个会话将从表中看到相同的当前最大 ID,并且都插入相同的新 ID 值。安全使用它的唯一方法是在开始事务之前锁定表,这很痛苦并且会序列化事务。(正如 Stijn 指出的那样,如果删除了最高记录,则可以重用值)。基本上,永远不要使用这种方法。(有时可能有一个令人信服的理由这样做,但我不确定我是否见过)。
该序列保证两个会话将获得不同的值,并且不需要序列化。它将表现得更好、更安全、更容易编码和更容易维护。
使用序列获得重复错误的唯一方法是,如果表中已经存在 ID 高于序列值的记录,或者在不使用序列的情况下仍在插入记录。因此,如果您有一个带有手动输入 ID 的现有表,例如 1 到 10,并且您创建了一个默认起始值为 1 的序列,则使用该序列的第一个插入将尝试插入一个 ID 为 1 - 已经存在. 在尝试了 10 次之后,序列会给你 11,这会起作用。如果您随后使用 max-ID 方法进行下一次插入,该插入将使用 12,但序列仍将在 11 上,并且下次调用时也会给您 12 nextval
。
序列和表格不相关。如果将手动生成的 ID 值插入表中,则不会自动更新序列,因此这两种方法不会混合使用。(除其他外,可以使用相同的序列为多个表生成 ID,如文档中所述)。
如果您要从手动方法更改为序列方法,则需要确保创建的序列的起始值高于表中所有现有 ID,并且执行插入的所有操作都使用该序列只在未来。