首页 > 解决方案 > MySQL在最大化时重用错过的主键int值

问题描述

我们的一张桌子意外地用完了 ID。快速浏览一下表格,我可以看到并非所有 ID 都已使用。我假设我们可能出于某种原因删除了数据。

我一直在阅读 mysql 的 auto_inc 字段的性质意味着它总是为下一个 ID 变为 +1。

有没有办法告诉它使用未使用的 ID?

我一直在这里阅读:https ://dev.mysql.com/doc/refman/5.7/en/innodb-auto-increment-handling.html 但我不是超级数据库开发人员,我真的不是得到如果这会做我所希望的。

我们的第一个计划是将 Id 更改为 Unsigned() 并获得额外的数十亿行。但这是对我们不应该接近的问题的快速解决方案。该表在生产中不断使用,但我们的系统确实有“重试”概念。因此,如果这张表暂时无法使用,那对我们来说很好。

任何指针或想法将不胜感激。干杯

标签: mysqlindexingalter-table

解决方案


要回答您的问题:

不,没有办法告诉 MySQL 的自动增量来生成“填补表中的空白”的值。

即使您尝试更改表格以重置下一个增量值,它也会立即将自身调整到当前的 MAX(id)+1。它不会生成小于表中当前最大自动增量的自动增量值。

您可以执行 INSERT 以覆盖自动增量并自己指定值。但您可以自行决定是否找到未使用的值。

这引入了竞争条件。即使您检查未使用的值,其他客户端也可以在您读取该值后立即获取它,然后再将其用于 INSERT。

为了避免竞争条件,您必须锁定整个表,以防止另一个客户端插入。然后您的会话可以进行查询以查找缺失值,然后插入,然后解锁表。

限制自动增量不填补空白有几个很好的理由。

  • 它简化了内部实现。它只需要跟踪每个表的一个值。更简单的实现通常意味着更少的错误机会。

  • 搜索下一个值不需要表锁。分配下一个值是通过一个简短的互斥锁来实现的。这允许许多并发客户端自由插入,无需等待。

  • 差距可能有充分的理由。

这个场景有点复杂,但它说明了这样的场景可能存在:

假设表中的 id 12345users对应于一个因向其他用户发送骚扰电子邮件而被禁止的用户。他们的帐户被禁止和禁止,并且users他们帐户的表中的行被删除。稍后,如果您发现该间隙并假设它从未使用过,那么您将该 id 12345 分配给下一个新用户。不幸的是,它们现在与该被禁止用户的 id 相关联。

然后,不经常检查电子邮件的人发现了其中一封原始的滥用电子邮件。收件人抱怨用户 12345。但该 id 现在属于新的无辜用户,他们不应该被指责为发送骚扰电子邮件。


推荐阅读