当整数列上的auto_increment达到数据库中的max_value时会发生什么?

时间:2010-04-10 23:29:54

标签: database auto-increment integer-overflow lastinsertid

我正在实现一个数据库应用程序,我将使用JavaDB和MySQL作为数据库。我的表中有一个ID列,其类型为整数,我使用数据库auto_increment-function作为值。

但是当我获得超过2(或4)亿个帖子并且整数不够时会发生什么?整数是溢出并继续还是抛出的异常我可以处理?

是的,我可以更改为数据类型,但如何检查何时需要?我认为获取last_inserted_id()函数是有问题的,如果我使用long作为ID列的数据类型。

6 个答案:

答案 0 :(得分:47)

为了平息神经,请考虑一下:

假设您有一个数据库,每次用户在您的网站上执行某种交易时都会插入一个新值。

使用64位整数作为ID,这是溢出的条件: 如果世界人口达到60亿,那么如果地球上的每个人每天和每年每秒执行一次交易(没有休息),那么你的身份将需要80多年才能完成。

但是,只有谷歌在喝咖啡休息时偶尔会模糊地考虑这个问题。

答案 1 :(得分:45)

Jim Martin对MySQL文档§3.6.9. "Using AUTO_INCREMENT"的评论:

  

万一有任何问题,AUTO_INCREMENT字段/ DOES NOT WRAP /。一旦达到字段大小的限制,INSERT就会生成错误。 (按照杰里米科尔的说法)

使用MySQL 5.1.45进行快速测试会导致错误:

  

错误1467(HY000):无法从存储引擎读取自动增量值

您可以在插入时测试该错误并采取适当的措施。

答案 2 :(得分:9)

通过查看最大的ID,您将知道何时会溢出。你应该在任何异常甚至接近被抛出之前改变它。

实际上,您应该设计一个足够大的数据类型来开始。即使从头开始使用64位ID,您的数据库性能也不会受到影响。

答案 3 :(得分:6)

这里的答案陈述了会发生什么,但只有一个答案说明如何检测问题(然后只有在错误发生后)。通常,能够在它们成为生产问题之前检测到这些内容是有帮助的,因此我编写了一个查询来检测溢出即将发生的时间:

SELECT
  c.TABLE_CATALOG,
  c.TABLE_SCHEMA,
  c.TABLE_NAME,
  c.COLUMN_NAME
FROM information_schema.COLUMNS AS c
JOIN information_schema.TABLES AS t USING (TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME)
WHERE c.EXTRA LIKE '%auto_increment%'
  AND t.AUTO_INCREMENT / CASE c.DATA_TYPE
      WHEN 'TINYINT' THEN IF(c.COLUMN_TYPE LIKE '% UNSIGNED', 255, 127)
      WHEN 'SMALLINT' THEN IF(c.COLUMN_TYPE LIKE '% UNSIGNED', 65535, 32767)
      WHEN 'MEDIUMINT' THEN IF(c.COLUMN_TYPE LIKE '% UNSIGNED', 16777215, 8388607)
      WHEN 'INT' THEN IF(c.COLUMN_TYPE LIKE '% UNSIGNED', 4294967295, 2147483647)
      WHEN 'BIGINT' THEN IF(c.COLUMN_TYPE LIKE '% UNSIGNED', '18446744073709551615', 9223372036854775807) # need to quote because column type defaults to unsigned.
      ELSE 0
    END > .9; # 10% buffer

希望这能帮到某个地方。

答案 4 :(得分:0)

对于MySQL 5.6,3.6.9 Using AUTO_INCREMENT表示:

  

使用AUTO_INCREMENT列的最小整数数据类型,该列足够大以容纳您需要的最大序列值。当列达到数据类型的上限时,下一次生成序列号的尝试将失败。

答案 5 :(得分:-2)

我想分享一下我刚才的个人经历。使用Nagios + Check_MK + NDOUtils。 NDOUtils将所有检查存储在名为nagios_servicechecks的表中。主键是auto_increment int signed。当此限制为范围时,MySQL会发生什么?好吧,在我的情况下,MySQL删除所有记录,但最后一个。桌子现在几乎是空的。每次插入新记录时,旧记录都将被删除。不要为什么会这样,但事实是我丢失了所有记录。与Icinga(不是Nagios)一起使用的IDOUtils修复了这个问题,由bigint更改int。它没有产生错误。