如果插入不成功,避免递增主键?

Avoid incrementing primary key if insert is not successful?

我有一个“位置”table如下:

使用 API,如果我发送有效记录,table 将正常从索引 1 开始。如果我发送的内容由于 table 的限制(无效的外键、空字段等)而不会被接受,那么 table 自然不会接受,并且不会插入任何内容。但是,如果我发送另一个有效记录,而不是 id 2,它将被索引为 3,即使只有 table有一条记录,什么都没有被删除。有没有简单的方法可以避免这种情况?

谢谢!

考虑这个场景:您开始一个事务并执行一个 INSERT。 INSERT成功,分配了id 2。但是同一事务中的后续查询失败,必须回滚,包括成功的INSERT。

与此同时,另一个会话也进行了自己的插入,分配了 id 3。该事务已提交。现在,table 中有一行 ID 为 3,但没有一行 ID 为 2。

您想如何处理?

a) 在提交事务之前阻止所有并发插入。这是确保只使用连续值所必需的。

b) 将 auto-increment 实现为一个不断增长的未使用 id 值列表。应该允许列表增长到多少 space?

事实是 auto-increment 允许“间隙”或未使用的值是正常的。如果 INSERT 失败,或者事务被回滚,或者您稍后删除一行,则会在连续的 id 值序列中留下空白。

为了效率,这是必要的妥协。 Auto-increment 值必须是唯一的,但不需要连续。它们不是行号。如果你需要保证 id 值是连续的,你必须牺牲系统中的其他东西,例如并发插入。如果您删除一行,您会怎么做,您是否希望对所有后续行重新编号?

有些人想压缩他们的 id 值,因为他们担心他们会 运行 出来。我看到您的主键是 BIGINT UNSIGNED。

https://mariadb.com/kb/en/bigint/ 说:

The unsigned range is 0 to 18446744073709551615.

请记住,如果您从 0 开始 auto-increment 并每秒递增 100 万次,则 BIGINT UNSIGNED 将持续 18,446,744,073,709 秒,即超过 584,542 年。