当应用自动增量时,MySQL会重复使用已删除的ID吗?

时间:2013-09-09 05:40:46

标签: mysql auto-increment

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

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

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

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

提前致谢...

5 个答案:

答案 0 :(得分:16)

重启数据库时,InnoDB会重置auto_increment字段。

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

在MyISAM中不会发生这种情况,因为它会缓存最后一个增加的id。

<强>更新

此功能/错误自2003年以来一直存在,可能导致严重问题。以下面的例子为例,

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

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

  3. 正如我们所知,InnoDB重新启动后,可以重新发出ID 。因此,t2中的孤立行可能会错误地链接到t1中的新行。

  4.   

    此错误已在 MySQL 8.0.0 WL#6204 - InnoDB persistent max value for autoinc columns中得到解决。

         

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

答案 1 :(得分:8)

如果主键字段也是auto_increment,则无论删除多少行(或按什么顺序),都不会再次使用不再存在的ID,并且每行的字段会连续递增。

但是,当主键由多个字段组成(E.G.一个auto_increment字段和另一个字段)时,auto_increment字段将被重用,并且仅当删除的id是最后一个id时才会重复使用。这意味着如果您有1,2,3,4和5之类的值,并且删除字段值为5的行,则下一行的ID将为5.但是,如果您删除行如果id为2,则不再使用,下一行的id为6。

答案 2 :(得分:2)

如InnoDB引擎所述,如果在重新启动之前删除该行,则将重用最后使用的PK,因为它未被缓存。如果这个PK是另一个表中的外键(FK),可能会出现问题(FK地狱)。这就是我发现这个问题的方法,当一位小老太太拍摄到195厘米(!)时,因为被删除的人的附加数据被拿起。解决这个问题的方法是实现“删除级联”和“删除级联”。对于子表或(不是我的首选选项)来解决这个问题。

答案 3 :(得分:0)

As mentioned in answer :

InnoDB resets the auto_increment field when you restart the database.

When InnoDB restarts, it finds the highest value in the column and then start from there.

and this behavior could lead to Foreign key problem.

Fortunately from MySQL 8.0.0 it will be fixed. More info:

Bug #199 Innodb autoincrement stats los on restart

WL#6204: InnoDB persistent max value for autoinc columns

See BUG#199 on MySQL bugs.

Currently InnoDB does the following when a table is opened: SELECT MAX(c) FROM t; where c is the AUTOINC column name. This step is used to initialise the column's next autoinc value and allocation of autoinc values starts from this point. InnoDB also does this when it executes 'ALTER TABLE AUTO_INCREMENT=N;'.

...

InnoDB should keep track of the maximum value and on restart preserve that max value and start from there.

答案 4 :(得分:0)

如果该表属于InnoDB类型,则在某些情况下将重用已删除的ID。这是我所做的测试:

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

    创建表user(   id bigint(20)NOT NULL AUTO_INCREMENT,   主键(id), )ENGINE = InnoDB AUTO_INCREMENT = 2108 DEFAULT CHARSET = latin1;

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

  3. 调用deleteUser API,该API仅从用户表中删除行。

  4. 停止并启动数据库

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

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