76

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

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

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

4

6 回答 6

55

Jim Martin 来自§3.6.9 的评论。MySQL 文档的“使用 AUTO_INCREMENT” :

以防万一有任何问题,AUTO_INCREMENT 字段 /DOES NOT WRAP/。一旦达到字段大小的限制,INSERT 就会产生错误。(根据杰里米·科尔)

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

ERROR 1467 (HY000): 无法从存储引擎读取自增值

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

于 2010-04-11T00:10:25.720 回答
55

只是为了让神经平静下来,请考虑一下:

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

使用 64 位整数作为 ID,那么这就是溢出的条件:如果世界人口为 60 亿,那么如果地球上的每个人每天和每年(不休息)每秒执行一次交易(不休息),则需要超过 80你的身份证需要几年的时间。

即,只有谷歌需要在喝咖啡的时候偶尔模糊地考虑一下这个问题。

于 2011-05-16T09:26:33.667 回答
11

通过查看最大的 ID,您将知道它何时会溢出。您应该在任何异常接近被抛出之前对其进行更改。

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

于 2010-04-10T23:42:14.577 回答
8

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

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

希望这可以帮助某个地方的人。

于 2017-07-18T16:00:22.790 回答
0

对于 MySQL 5.6 ,3.6.9 中使用 AUTO_INCREMENT说:

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

于 2015-09-23T08:29:22.680 回答
-1

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

于 2015-11-26T18:33:53.770 回答