26

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

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

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

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

提前致谢...

4

5 回答 5

28

当您重新启动数据库时,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 将跟踪最大值并在重新启动时保留该最大值并从那里开始。

于 2013-09-09T05:49:44.833 回答
10

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

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

于 2013-09-09T05:50:42.233 回答
2

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

于 2016-04-01T16:21:03.260 回答
0

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

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

    CREATE TABLE user( idbigint(20) NOT NULL AUTO_INCREMENT, PRIMARY KEY ( id), ) ENGINE=InnoDB AUTO_INCREMENT=2108 DEFAULT CHARSET=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 也没有抱怨。当服务器重新启动时,用户规则就搞砸了!

于 2019-01-29T19:58:29.180 回答
0

答案中所述:

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

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

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

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

错误 #199 Innodb 自动增量统计信息在重启时丢失

WL#6204:innoDB 的 autoinc 列的持久最大值

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

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

...

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

于 2017-10-08T07:52:23.367 回答