当自增列耗尽时会发生什么?

25

考虑一个带有自增列的简单表格,就像这样:

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,但像Y2K问题一样,我想为此做好准备。

3个回答

63

假设每毫秒插入一行记录。

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

因此它并不像 Y2K 问题那样严重。

即使每毫秒插入 百万 行,也可以安全地使用超过 500 年。

换句话说:不用担心。


1
好的。我不认为我的应用程序会持续那么久 => 500年。 - ashitaka
2
同样地,如果你每秒只插入一次,使用32位有符号整数,你的应用程序将运行68年。每个记录节省4字节,如果可以,请使用32位整数。 - jmucchiello
3
如果使用较小的数据类型(例如INT)并发生溢出,会发生什么?假设固定大小的整数永远不会溢出,这并不是一个很前瞻性的想法。 - Joey Adams
12
@Joey: 所以你给我点了踩是因为我回答了实际被问到的问题,而不是你自己想问的问题?奇怪。为什么不直接问你感兴趣的问题呢?我认为如果整数的大小足够大,就可以合理地假设它永远不会溢出。如果你开始假设你的应用程序需要在500年内每毫秒处理一百万次请求,那么你几乎肯定会过度设计它。 - Jon Skeet
5
在遥远的未来,人们将从互联网上挖掘这个内容,并因为2008年不负责任的开发人员没有考虑它而归咎于@JonSkeet导致所有应用程序失败:D。 - brettwhiteman
显示剩余3条评论

19

根据你使用的 SQL 模式,当一个 AUTO_INCREMENT 数字列的值超出范围时,MySQL 会执行以下两个操作之一。在任何情况下都会收到错误提示,但原因不同。

严格模式 下,MySQL 拒绝超出范围的值,抛出一个无效值错误,并导致 INSERT 失败。在默认的 非严格模式 下,MySQL 会将值减少到数据类型允许的最高值,并执行 INSERT。但由于 AUTO_INCREMENT 属性已经使用了所有可能的值,因此会导致插入失败并收到如下错误(unsigned SMALLINT 示例):

MySQL said:

#1062 - Duplicate entry '65535' for key 1

在此 BIGINT 的示例中,用 18 个万亿替换 "65535",虽然这种错误很可能从未发生在生产数据库中。

但是对于 TINYINTSMALLINT,如果您低估了应用程序使用期间可能出现的键值数量(INSERT 的数量),那么这种错误很容易发生。想象一下,当您更改代码并测试数据是否被正确插入时,突然出现上述错误导致您的应用程序停止工作。您回滚到已知的良好代码,但错误仍然存在 …… 这非常令人沮丧。


2

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


2
MySQL 中不可用。 - Rick James

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接