当自动递增列用完时会发生啥?

Posted

技术标签:

【中文标题】当自动递增列用完时会发生啥?【英文标题】:What happens when an auto-incrementing column runs out?当自动递增列用完时会发生什么? 【发布时间】:2010-09-26 14:26:19 【问题描述】:

考虑一个具有如下自动增量列的简单表:

CREATE TABLE foo 
(
  `fooid` bigint unsigned NOT NULL auto_increment,
   ....snipped.... other columns
  PRIMARY KEY (`fooid`)
) 
ENGINE=InnoDB AUTO_INCREMENT=10

如何重新设计这一点,以免我们达到 bigint 数据类型的最大值? 无符号范围是 0 到 18446744073709551615。 不知道需要多长时间才能到达18446744073709551615,但就像千年虫问题一样,我要做好准备。

【问题讨论】:

【参考方案1】:

假设您每毫秒插入一行。

18446744073709551615 毫秒 = 18446744073709552 秒 = 307445734561826 分钟 = 5124095576030 小时 = 213503982335 天 = 584942417年

所以它真的不像千年虫问题

您可以每毫秒插入 百万 行,并且在 500 多年内仍然可以使用。

换句话说:别担心。

【讨论】:

好的。我认为我的应用不会持续那么久 => 500 年。 类似地,如果您每秒只插入一次,您的应用程序将使用 32 位带符号的 int 运行 68 年。为每条记录节省 4 个字节,并尽可能使用 32 位 int。 我想知道如果您使用较小的类型(例如 INT)并且它溢出会发生什么。假设固定大小的整数永远不会溢出,这不是很有远见。 @Joey:所以你对我投了反对票,因为我已经回答了实际被问到的问题,而不是你自己会问的问题?奇怪的。为什么不问你感兴趣的问题呢?我认为假设一个固定大小的整数在大小足够大时永远不会溢出是完全合理的。如果您开始假设您的应用需要在此期间以每毫秒一百万次点击运行 500 多年,那么您几乎肯定会过度设计它。 在遥远的未来,人们会从互联网上挖掘这个问题,并将所有失败的应用程序归咎于 @JonSkeet,因为 2008 年不负责任的开发人员并不担心:D【参考方案2】:

根据您使用的SQL mode,当AUTO_INCREMENT 数值列的值超出范围时,mysql 会执行以下两种操作之一。无论哪种情况,您都会收到错误,但原因不同。

严格模式 MySQL 拒绝超出范围的值,抛出无效值错误,INSERT 失败。在默认的非严格模式中,MySQL 将值减小到数据类型允许的最大值,并执行INSERT。但是INSERT 失败了,因为AUTO_INCREMENT 属性导致所有可能的值都已被使用,并且您会收到此错误(无符号SMALLINT 示例):

MySQL said:

#1062 - Duplicate entry '65535' for key 1

对于此处的 BIGINT 示例,将“65535”替换为 18 quintillion,尽管生产数据库上不太可能发生此错误。

但是对于TINYINTs 和SMALLINTs,如果您低估了应用程序生命周期内可能的键值(INSERTs 的数量),则很容易发生这种情况。想象一下,您正在对代码进行更改并测试您的数据是否正确插入。突然,您的应用程序因上述错误而退出工作。您将更改回滚到已知良好的代码,但错误不会消失...非常令人沮丧。

【讨论】:

【参考方案3】:

不知道MySQL,但如果是Postgresql,可以指定序列是CYCLE/NO CYCLE。如果使用 CYCLE 选项创建,它将再次返回 1(或最小值)并会抛出重复键的错误。

【讨论】:

在 MySQL 中不可用。

以上是关于当自动递增列用完时会发生啥?的主要内容,如果未能解决你的问题,请参考以下文章

当我用尽 bigint 生成的密钥时会发生啥?如何处理?

当我用尽 bigint 生成的密钥时会发生啥?如何处理?

当自动关闭资源时尝试使用资源引发异常以及异常时会发生啥

6. Redis在内存用完时会怎么办?以及Redis如何处理已过期的数据?

在具有自动内存管理的编程环境中,OS内存分配例程在运行时调用的频率是多少?

数据源用完时如何停止火花流