【问题标题】:Why PRIMARY_KEY is not deleted permanently? [duplicate]为什么 PRIMARY_KEY 没有被永久删除? [复制]
【发布时间】:2014-02-27 13:55:00
【问题描述】:

如果我在数据库中有一个表和一个包含AUTO_INCREMENTPRIMARY_KEY 列的表。

假设表中总共有 5 行。

现在考虑这种情况......

我删除了5th 行。

下次我将INSERT 一行,它将有PRIMARY_KEY 6

为什么已删除记录的键也没有被永久删除?

如果这些记录被保留以识别针对该密钥存储了哪些记录,那么我们怎么知道那是什么记录,因为它已被删除。

【问题讨论】:

  • 因为在任何主要的 RDBMS 中,自动增量、标识或序列都不是这样工作的。一旦分配了号码,它就会被烧毁。永远消失了。
  • 它的目的是保证唯一性,而不是顺序性(这只是使事物独一无二的一种简单方法)。如果填补了删除的空白,则外键关系可能会混乱

标签: mysql sql database


【解决方案1】:

主键是行的唯一标识符。它们不应该被回收。

考虑一下您插入 ID 为“123”的用户的场景,然后有人删除了该记录,然后插入了一条新记录。 RDBMS 回收 ID。

然后你回来寻找ID为“123”的用户,当然你得到的是其他用户,而不是你想要的。

听起来很像完整性约束和实体完整性的问题。

【讨论】:

    【解决方案2】:

    确实如此。 auto_increment 始终是最后一个值 + 1。 您可以更改auto_increment 的当前值,但不能定义更低的值。

    有关更多信息,请阅读此主题: Changing the current count of an Auto Increment value in MySQL?

    解决您问题的另一种方法是通过我们的主键定义主键:

    INSERT tableName (id, field1, field2) VALUES((SELECT COUNT(*) + 1 FROM tableName),"value1","value2")
    

    【讨论】:

    • 不要通过获取表中所有记录的计数加一来实现虚假的自动递增键。在某些数据库中它可能会变得非常昂贵。
    【解决方案3】:

    大多数自动增量方案的工作方式是数据库记住为每个此类字段分配的最后一个数字,并且插入的下一条记录总是+1。所以它只需要记住 1 个数字:分配的最后一个数字。

    假设您插入了 5 条记录。他们得到 1、2、3、4、5。现在删除 2 和 4。数据库如何知道在接下来的两次插入中重复使用 2 和 4?

    我想,它可以在每次插入时扫描表中的所有记录,寻找序列中的第一个孔。但是每次插入都需要读取表中的每条记录。如果表有数百万条记录会怎样?插入可能需要几分之一毫秒到几分钟。

    它可以保存一张已删除记录的表格。据推测,它每次插入时都会将第一个数字从表中拉出。但是,现在每个插入都是:检查表。有记录吗?如果是这样,取那个号码,删除记录。如果没有,请取下一个可用的号码。该表必须同步,以便如果多个用户正在添加记录,我们不会两次给出相同的数字。如果有很多删除,它可能会变得非常大。即使每次执行插入时只是额外读取一次,我们现在也执行两次操作而不是一次:性能将减半。

    好的,我们可以处理迄今为止分配的最高数字被删除的特殊情况,然后从我们迄今为止分配的最高数字中减去 1。可行,但是否值得为那个特殊情况制定特殊规则?您多久删除一次插入的最后一条记录?如果删除基本上是随机发生的,那么该记录将被删除的可能性很小。

    总是分配一个新号码有明显的优势:

    一:简单。这种行为是直截了当且易于预测的。没有特殊情况。

    二:速度。如前所述,替代方案需要额外的工作。也许不是很多,但如果我们只需要为每个插入处理一个额外的记录,我们的性能就会降低一半。

    三:我们可以使用分配的编号来告诉我们添加记录的顺序。高数记录总是比低数记录更新。在进行临时查询和跟踪问题时,我经常发现这很方便。

    四:我们避免潜在的错误连接。假设您向表 A 添加一条记录,并为其分配编号 12。然后您向表 B 添加一条记录,其中包含对表 A 的引用,因此我们插入该编号 12。假设对于各种您不将其声明为外键的原因。然后你从表 A 中删除记录 12。所以现在你在表 B 中有这个悬空引用。这很糟糕。但是想象一个新的记录被添加到 A 并且它得到一个循环的数字 12。现在我们在 B 中有一条记录指向 A 中的错误记录。悬空指针是不好的,但错误的指针更糟糕。客户因他人的指控而被收取费用,或因犯罪而被错误逮捕的人等。

    更复杂的系统会有什么好处?我看到的唯一好处是,我们将减少用尽可能数字的可能性。但是如果序列号是一个 4 字节的整数,那么就有 20 亿个可能的值。有多少表在其生命周期内获得 20 亿次插入?当然,如果表有 50 亿条记录,那么无论您是否尝试重用数字,您都会遇到问题。我想如果您有一些非常大容量的队列,其中不断添加新记录而丢弃旧记录,这可能是一个问题。或者,如果您经常删除记录并重新插入它们,而不是在原地进行更新。但坦率地说,我从事这项业务已有 30 年了,我从来没有遇到过问题,因为数据库中的自动序列用完了数字。我不怀疑它发生在某个地方的某个人身上,但这不是一个常见的问题。我不认为它很常见到足以破坏一个干净、简单的系统。

    【讨论】:

      【解决方案4】:

      您不想要重复使用数字。它没有任何优势。它们毫无意义。不要依赖具有任何给定值的任何 ID 的值。

      【讨论】:

        猜你喜欢
        • 2013-08-18
        • 1970-01-01
        • 2012-09-22
        • 1970-01-01
        • 2016-10-28
        • 1970-01-01
        • 2015-12-10
        • 2013-06-19
        • 1970-01-01
        相关资源
        最近更新 更多