我正在实现一个数据库应用程序,将使用JavaDB和MySQL作为数据库。我的表中有一个ID列,类型为整数,并且我使用数据库的auto_increment函数来生成该值。
但是,当我拥有超过20亿(或40亿)个帖子时,整数会发生溢出并继续增长吗?还是会抛出异常,以便我可以处理?
是的,我可以将数据类型更改为long,但我怎样才能知道何时需要进行更改呢?如果我将ID列的数据类型更改为long,可能会出现获取last_inserted_id()函数的问题。
我正在实现一个数据库应用程序,将使用JavaDB和MySQL作为数据库。我的表中有一个ID列,类型为整数,并且我使用数据库的auto_increment函数来生成该值。
但是,当我拥有超过20亿(或40亿)个帖子时,整数会发生溢出并继续增长吗?还是会抛出异常,以便我可以处理?
是的,我可以将数据类型更改为long,但我怎样才能知道何时需要进行更改呢?如果我将ID列的数据类型更改为long,可能会出现获取last_inserted_id()函数的问题。
来自 MySQL 文档 §3.6.9. "使用 AUTO_INCREMENT" 的 Jim Martin 评论:
以防万一,AUTO_INCREMENT 字段 /不会循环/. 一旦达到字段大小的极限,插入操作将生成错误。(根据 Jeremy Cole)
使用 MySQL 5.1.45 进行快速测试会导致以下错误:
ERROR 1467 (HY000): Failed to read auto-increment value from storage engine
您可以在插入时测试该错误并采取适当的措施。
为了平静神经,考虑以下情况:
假设您有一个数据库,在用户在您的网站上执行某些事务时插入新值。
如果使用64位整数作为ID,则溢出条件如下: 如果世界人口为60亿,那么如果地球上的每个人每秒钟每天和每年都执行一次交易(不休息),则需要超过80年才能使您的ID回到原点。
也就是说,只有谷歌需要在咖啡时间偶尔考虑这个问题。
int(10) unsigned
,id列在短短2个月内就已经达到了237836414
,占用了uint_max的5.54%。所以,这是一个问题。 - majidarif这里的答案阐述了会发生什么,但是只有一个答案说出如何检测问题(而且只有在错误发生后才能检测出来)。通常,在它们成为生产问题之前能够检测到这些问题是很有帮助的,因此我编写了一个查询以检测溢出即将发生的情况:
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
使用足够大以容纳所需最大序列值的最小整数数据类型作为AUTO_INCREMENT列。当该列达到数据类型的上限时,下一次尝试生成序列号将失败。