自增值达到上限怎么办?
What to do if the auto-increment value reaches its limit?
我正在研究某天可能会出现的问题。
假设你有一个 InnoDB MySQL table 带有一个 id 和一个 name 字段。 id 字段有 BIGINT(20) 并且是 AUTO_INCREMENT 加上它的主键。
如果这个 table 已满,这意味着我们已经达到了 id 的限制,并且无法再生成自动递增编号,您会怎么做。
tinyint: 1 byte, -128 to +127 / 0 to 255 (unsigned)
smallint: 2 bytes, -32,768 to +32,767 / 0 to 65,535 (unsigned)
mediumint: 3 bytes, -8,388,608 to 8,388,607 / 0 to 16,777,215 (unsigned)
int/integer: 4 bytes, -2,147,483,648 to +2,147,483,647 / 0 to 4,294,967,295 (unsigned)
bigint: 8 bytes, -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807 / 0 to 18,446,744,073,709,551,615 (unsigned)
你是不是觉得这个数字很小?
也许你在达到这个数字之前就已经死了
让我们假设一个 table 结构如下:
CREATE TABLE `tbl` (
`id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id`)
);
和 INSERT
查询如:
INSERT INTO tbl(id) VALUES (NULL);
在实际代码中 table 中还有其他列,它们也出现在 INSERT
查询中,但我们可以安全地忽略它们,因为它们不会为此带来任何价值具体问题。
当列 id
的值达到最大值时,无法使用上述查询在 table 中插入更多行。下一个 INSERT
失败并显示错误:
SQL Error (167): Out of range value for column 'id'.
如果 id
列的值存在间隙,那么您仍然可以插入使用 table 中不存在的值的行,但您必须指定 id
的值] 在 INSERT
查询中。
无论如何,如果您的 AUTO_INCREMENT
列的类型是 BIGINT
,您就不必担心。
假设代码每秒插入 一百万条记录(这被高估了,不能说不可能),id
列的值足够下一个 half of million years。或者如果该列不是 UNSIGNED
.
,则只是 292,277
年
我目睹了使用 INT(11)
(而不是 UNSIGNED
)作为 AUTO_INCREMENT
ed PK 记录信息的 table 的实时网络服务器上的行为关于网站的访问。半夜失败了,经过几年运行的顺利,当访问量达到2^31
(2
亿什么的)。
将列类型从 INT
更改为 BIGINT
不是针对 20 亿条记录的解决方案 table(需要很长时间才能完成,当系统上线时,那里时间永远不够)。解决方案是创建一个具有相同结构但 PK 列为 BIGINT
且 AUTO_INCREMENT
列为初始值的新 table,然后切换 table:
CREATE TABLE `tbl_new` (
`id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id`)
) AUTO_INCREMENT=2200000000;
RENAME TABLE `tbl` TO `tbl_old`, `tbl_new` TO `tbl`;
我正在研究某天可能会出现的问题。 假设你有一个 InnoDB MySQL table 带有一个 id 和一个 name 字段。 id 字段有 BIGINT(20) 并且是 AUTO_INCREMENT 加上它的主键。
如果这个 table 已满,这意味着我们已经达到了 id 的限制,并且无法再生成自动递增编号,您会怎么做。
tinyint: 1 byte, -128 to +127 / 0 to 255 (unsigned)
smallint: 2 bytes, -32,768 to +32,767 / 0 to 65,535 (unsigned)
mediumint: 3 bytes, -8,388,608 to 8,388,607 / 0 to 16,777,215 (unsigned)
int/integer: 4 bytes, -2,147,483,648 to +2,147,483,647 / 0 to 4,294,967,295 (unsigned)
bigint: 8 bytes, -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807 / 0 to 18,446,744,073,709,551,615 (unsigned)
你是不是觉得这个数字很小? 也许你在达到这个数字之前就已经死了
让我们假设一个 table 结构如下:
CREATE TABLE `tbl` (
`id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id`)
);
和 INSERT
查询如:
INSERT INTO tbl(id) VALUES (NULL);
在实际代码中 table 中还有其他列,它们也出现在 INSERT
查询中,但我们可以安全地忽略它们,因为它们不会为此带来任何价值具体问题。
当列 id
的值达到最大值时,无法使用上述查询在 table 中插入更多行。下一个 INSERT
失败并显示错误:
SQL Error (167): Out of range value for column 'id'.
如果 id
列的值存在间隙,那么您仍然可以插入使用 table 中不存在的值的行,但您必须指定 id
的值] 在 INSERT
查询中。
无论如何,如果您的 AUTO_INCREMENT
列的类型是 BIGINT
,您就不必担心。
假设代码每秒插入 一百万条记录(这被高估了,不能说不可能),id
列的值足够下一个 half of million years。或者如果该列不是 UNSIGNED
.
292,277
年
我目睹了使用 INT(11)
(而不是 UNSIGNED
)作为 AUTO_INCREMENT
ed PK 记录信息的 table 的实时网络服务器上的行为关于网站的访问。半夜失败了,经过几年运行的顺利,当访问量达到2^31
(2
亿什么的)。
将列类型从 INT
更改为 BIGINT
不是针对 20 亿条记录的解决方案 table(需要很长时间才能完成,当系统上线时,那里时间永远不够)。解决方案是创建一个具有相同结构但 PK 列为 BIGINT
且 AUTO_INCREMENT
列为初始值的新 table,然后切换 table:
CREATE TABLE `tbl_new` (
`id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id`)
) AUTO_INCREMENT=2200000000;
RENAME TABLE `tbl` TO `tbl_old`, `tbl_new` TO `tbl`;