【问题标题】:Will MySQL reuse deleted ID's when Auto Increment is applied应用自动增量时 MySQL 是否会重用已删除的 ID
【发布时间】:2013-09-12 13:52:35
【问题描述】:

http://dev.mysql.com/doc/refman/5.0/en/example-auto-increment.html

我正在阅读的那个文件似乎是这样说的:

“在这种情况下(当 AUTO_INCREMENT 列是多列索引的一部分时),如果您删除任何组中具有最大 AUTO_INCREMENT 值的行,则会重用 AUTO_INCREMENT 值。”

我真的不明白那里在说什么。值不应该自动重用吗?

提前谢谢...

【问题讨论】:

标签: mysql auto-increment


【解决方案1】:

当你重新启动数据库时,InnoDB 会重置 auto_increment 字段。

当 InnoDB 重新启动时,它会找到列中的最大值,然后从那里开始。

这在 MyISAM 中不会发生,因为它缓存了最后增加的 id。

更新

此功能/错误自 2003 年以来一直存在,可能会导致严重问题。举个例子,

  1. 表 t1 有一个 auto-inc 主键。

  2. 表 t2 在 t1 中有一个主键列,没有外键“约束”。换句话说,当 t1 中的一行被删除时,t2 中的相应行就会被孤立。

  3. 正如我们所知道的 InnoDB 重启,一个 id 可以被重新发布。因此,t2 中的孤立行可能会错误地链接到 t1 中的新行。

这个错误终于在 MySQL 8.0.0 WL#6204 - InnoDB persistent max value for autoinc columns 中得到修复。

InnoDB 将跟踪最大值并在重启时保留 最大值并从那里开始。

【讨论】:

  • 所以删除的ID没有被重用?
  • 不,除了上述情况和@Parham Doustdar 之外,它们不会被重复使用
  • 上面的case好像是说最后一个id需要删除。这是否必须通过查询手动完成?
  • 如果你担心 InnoDB 在重启时会丢失 auto_increment 轨道,你可以按照这里提到的方法之一dba.stackexchange.com/questions/16602/…
  • 我也以为是这样的,但是我们的数据库不断有新条目的主键低于最高主键,我们之前删除了一个条目,所以我很困惑..
【解决方案2】:

当你有一个也是auto_increment的主键字段时,无论删除多少行(或以什么顺序),不再使用的id都不再使用,并且该字段对于每一行都连续递增。

但是,当您的主键包含多个字段(例如,一个 auto_increment 字段和另一个字段)时,auto_increment 字段会被重用,并且仅当删除的 id 是最后一个 id 时。这意味着如果您有 1、2、3、4 和 5 之类的值,并且您删除了字段值为 5 的行,那么下一行的 id 将为 5。但是,如果您使用id 为 2,这将再次不被使用,下一行的 id 为 6。

【讨论】:

  • 如果primary达到最大值会怎样,是否会重用已删除的id?
【解决方案3】:

如 InnoDB 引擎所述,如果在重新启动之前删除了该行,则最后使用的 PK 将被重用,因为它没有被缓存。如果此 PK 是另一个表中的外键 (FK),则可能会出现问题(FK 地狱)。这就是我发现问题的方式,当时一位小老太太身高达到 195 厘米(!),因为删除的人的附加数据被拾取。解决此问题的方法是为子表实现“ON DELETE CASCADE”或(不是我的首选选项)围绕此问题编写代码。

【讨论】:

  • 此行为将从 MySQL 8.0.0 更改
【解决方案4】:

answer 中所述:

InnoDB 会在您重新启动数据库时重置 auto_increment 字段。

当 InnoDB 重新启动时,它会在列中找到最大值,然后从那里开始。

这种行为可能会导致外键问题。

幸运的是来自MySQL 8.0.0,它将被修复。 更多信息:

Bug #199 Innodb autoincrement stats los on restart

WL#6204: InnoDB persistent max value for autoinc columns

请参阅关于 MySQL 错误的 BUG#199。

目前 InnoDB 在一个表时执行以下操作 打开:SELECT MAX(c) FROM t;其中 c 是 AUTOINC 列名。 此步骤用于初始化列的下一个 autoinc 值和 autoinc 值的分配从这一点开始。 InnoDB 也这样做 当它执行“ALTER TABLE AUTO_INCREMENT=N;”时。

...

InnoDB 应该跟踪最大值并在重启时保留 最大值并从那里开始。

【讨论】:

    【解决方案5】:

    如果表是 InnoDB 类型,那么删除的 id 在某些场景中会被重用。这是我为测试它所做的:

    1. 表用户有 id 列作为主键,并设置了 auto_increment

      创建表user ( id bigint(20) NOT NULL AUTO_INCREMENT, 主键 (id), ) ENGINE=InnoDB AUTO_INCREMENT=2108 默认字符集=latin1;

    2. 我的 createUser API 调用,在用户表中创建一个条目。假设创建了 id = 1 的用户。

    3. 调用 deleteUser API,它只是从用户表中删除行。

    4. 停止和启动数据库

    5. 再次调用 createUserAPI 调用。它创建具有相同 id (id = 1) 的用户。

    因此,如果服务器重新启动,它确实会使用已删除的 id。 我遇到了这个问题,因为我有另一个名为 user_rules 的表,它将 user_id 存储在一列中,但它没有对用户表的 FK 引用(这是错误的)。另一个问题是,当用户被删除时,user_rules 表中的条目没有被删除,并且由于它没有设置 FK,db 也没有抱怨。 当服务器重新启动时,用户规则就搞砸了!

    【讨论】:

      猜你喜欢
      • 2012-06-08
      • 2014-01-09
      • 2012-11-18
      • 1970-01-01
      • 2015-09-28
      • 2011-01-13
      • 2011-12-26
      相关资源
      最近更新 更多