【问题标题】:How to reuse auto_increment values? [duplicate]如何重用 auto_increment 值? [复制]
【发布时间】:2012-04-02 08:12:05
【问题描述】:

可能重复:
Fragmentation of id's (auto_increment column) in mysql

我的数据库中有此列。假设它的名字是'threadid'。 它包含为每个线程分配的唯一 ID 以进行区分。

线程ID 9 8 7 6 5 4 3 2 1

假设我删除了 id 为 5 和 6 的线程。

线程ID 9 8 7 4 3 2 1

但是当删除后有提交的时候,给那个线程的唯一id是10。不是5。我觉得这不整洁。

如何在列中获得尽可能少的值? (在本例中为 5。)

我认为我可以使用 MIN() 获取列的最小值并保持 +1,直到我得到未使用的唯一值,但我认为这太复杂了。

有什么简单的方法吗?

谢谢。

【问题讨论】:

  • 我知道这并不重要,但很好奇你为什么想要这个?只是为了保持数字干净,还是为了别的?
  • @jprofitt 我同意;在bigint(20) 列中,ID 值中的间隙并不重要(:
  • 这个问题每周都会出现几次。底线是:您不想“重用”丢失的号码。原因有很多,不适合评论一一列举。如果您想要“漂亮”的有序数字,请不要使用 auto_increment 。 auto_increment 有一个且只有一个目的 - 唯一地 标识一行。而已。那里没有“它很漂亮”。如果必须有一个很好的顺序编号,创建另一个列并通过触发器维护它。
  • 我不同意谁对此投反对票,仅仅因为实现不是规范并不意味着它没有用处,在某些情况下,必须这样做。我要对此投赞成票。
  • @所有不同意的人。就像我说的,它是实现的要求,因此你必须想出一个解决方案。如果你能想出一个不同的,那就是我的猜测。这应该是一个问答论坛,您应该提出问题的答案,而不是我的选择或应该做什么。有用于讨论最佳实践的programmer.stackexchange.com。

标签: mysql database auto-increment


【解决方案1】:

它包含唯一 ids 给每个线程用于区分。

你是这么说的。
唯一身份。为了区别。

如何才能称 ID 为唯一?
当今天某个主题有一个 id 和一个 next day - 另一个时,会有什么区别?
怎么找回来?
您将如何将其链接到其他线程?

试着想想这些词的意思。之所以称它为独特

不要把孩子当成只是为了快乐而想要“整洁”和“可爱”的东西的孩子,而是作为一个可以看到后果的成年人。

尝试学习倾听更有经验的人,并遵循他们基于知识和经验的建议,而不仅仅是你的突发奇想。

【讨论】:

  • 为您的个人资料中指向您网站的链接投票支持您的答案。
【解决方案2】:

如果您每分钟创建 1000 个线程,则 MySQL 中 INT 的最大数量为 4294967295,您每天需要 1440000 (1000 x 60 x 24) 个 id。所以你会在大约 8.17 年后用完 id。

BIGINT 的最大数量为 18446744073709551615,这足以在 35096 年中每分钟创建 1000000000(10 亿)个 ID

因此,您可以随心所欲地浪费 id 而不必担心它们。

【讨论】:

  • 这听起来不错。我想我不必担心。我没有看到你的答案。所以我做了我自己的数学,结果是一样的。我不必担心。留有空隙。
  • 解释清楚,谢谢。
【解决方案3】:

我同意其他人的观点,即实施自己的找到最小开放数是一个非常糟糕的主意。但是在我工作的地方,我们得到了一组封闭的数字,当一个数字空闲时,我们必须重复使用。

我们是这样做的。

我们不删除行,而是将每一列的所有值设置为空,所以你要做的是 SELECT min(id) WHERE columnA IS NULL,如果返回值,我们重用,否则,插入新行。

【讨论】:

  • 这类似于称为软删除的模式。
  • 我看到很多潜在的死锁(多个并发连接尝试执行“插入”)或只是简单的性能开销,首先必须检查是否有可用的空行,然后插入之后。您刚刚显着增加了应用程序的复杂性,为了什么,序号?给你自己和继承这个应用程序的人一个巨大的帮助,忘记这一点。此外,如果您使用外键,这确实会产生一些非常不一致的数据。
  • 正如@Devin 所说的那样,这是一种解决僵局的好方法。
  • 我没有看到死锁问题,如果您在插入时使用显式表锁,则可以防止两个会话获得相同的数字。如果您简单地使用SELECT id WHERE columnA IS NULL LIMIT 1,则此方法是可行的,性能只有轻微的损失,假设列 A 上有一个索引。
  • 这是很久以后的事了,但是 Churk 说,在我工作的地方,我们得到了一组封闭的数字[s]"。限制迫使他使用不是最佳实践的解决方案。您应该为没有非程序员施加此类限制而感到幸运。所以,请停止抱怨,让有政治/商业限制的人休息一下。OP 的问题是有效,并且 Churk 的回答是一个聪明的解决方案。
【解决方案4】:

因此,为了参照完整性,我不建议重复使用 ID。使用 int 和 bigint 的最大限制,您永远不会用完唯一值。唯一值是参考数据库的核心。

话虽如此,您可以运行搜索子例程(或代替触发器)来查找最低的可用 id。然后暂时关闭标识插入,插入数据,然后重新打开标识插入。

有很多理由不这样做!其中包括当多个值同时进入时插入数据之间的所有潜在冲突。

【讨论】:

  • 另外,如果你真的想保留一个连续数字的漂亮列表,你可以考虑添加一个“停用”标志。这样你就不会预先删除任何东西。您可以稍后将其重新索引为作业。同样,这会破坏您的参照完整性,但您可以做到...
【解决方案5】:

帮自己一个忙,忘记这件事。实施这将是一个巨大的痛苦,所以除非有一个非常引人注目的目标要实现,否则无法实现(不太可能)我们谈论巨大的痛苦没有收获。

MySql 本身不支持这种情况正是因为这个原因:大量复杂化无益。

【讨论】:

    【解决方案6】:

    除非整个表被截断,否则 MySQL 将保持 ID 的顺序。删除行不会影响最后一个 ID。

    【讨论】:

      猜你喜欢
      • 2015-11-10
      • 2015-04-15
      • 2013-05-18
      • 2016-07-06
      • 1970-01-01
      • 2020-02-10
      • 2013-03-16
      • 2021-10-02
      • 2015-03-25
      相关资源
      最近更新 更多