MySQL中的自增主键 ID自增到最大,使用完id会发生什么,怎么办?

Posted Agly_Charlie

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MySQL中的自增主键 ID自增到最大,使用完id会发生什么,怎么办?相关的知识,希望对你有一定的参考价值。

背景

之前的学习和实践上了解到的是:

SQL插入异常,主键冲突错误,因为自增ID达到上限后,再申请时它的值不会改变,继续插入数据会导致报主键冲突错误

/* SQL Error (1062): Duplicate entry '2147483647' for key 'PRIMARY' */

但我在偶然中发现,还会有这个错误信息,读取自增ID失败。

/* SQL Error (1467): Failed to read auto-increment value from storage engine */

测试过程

于是产生了进一步实验的想法,以下是操作过程:
本次测试环境MySQL 5.7.22

创建表,自增ID

CREATE TABLE `tb_id_incr` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`name` INT(11) NULL DEFAULT NULL,
PRIMARY KEY (`id`)
)
ENGINE=InnoDB;

场景一:测试自增ID已经达到最大值

  • 第1步:测试,直接让表记录自增ID达到最大值:
INSERT INTO `tb_id_incr` (`id`, `name`) VALUES ('2147483647', '3');

在这里插入图片描述

  • 第2步:达到最大值后,再insert一条记录
INSERT INTO `tb_id_incr` (`name`) VALUES ('3');
/* SQL Error (1062): Duplicate entry '2147483647' for key 'PRIMARY' */

在这里插入图片描述

  • 第3步:达到最大值后,再insert 多个记录,
INSERT INTO `tb_id_incr` (`name`) VALUES ('3'),('4'),('5'),('6'),('7'),('8'),('9')
/* SQL Error (1062): Duplicate entry '2147483647' for key 'PRIMARY' */

在这里插入图片描述

结论:都产生主键冲突错误

场景二:测试自增ID即将达到最大值

  • 第1步:让表记录自增ID 即将达到最大值:
INSERT INTO `tb_id_incr` (`id`, `name`) VALUES ('2147483640', '3');

在这里插入图片描述

  • 第2步:还没达到最大值后,再insert 多个记录,
INSERT INTO `tb_id_incr` (`name`) VALUES ('3'),('4'),('5'),('6'),('7'),('8'),('9'),('3'),('4'),('5'),('6'),('7'),('8'),('9'),('5'),('6'),('7'),('8'),('9');
/* SQL Error (1467): Failed to read auto-increment value from storage engine */

在这里插入图片描述

  • 第3步:查看内部自增ID
    查看show create table的值已达到最大ID,表明批量插入失败,但还是会继续消耗ID,自增到最大后,报错提示读取自增ID失败
    在这里插入图片描述

总结

自增ID用完了,会发生两种情况:

  1. 如果是已经是最大ID了,那么会报错:主键冲突:
/* SQL Error (1062): Duplicate entry '2147483647' for key 'PRIMARY' */
  1. 如果是即将到达最大值,并且此时批量插入的记录条数大于剩余可用的ID数,会继续消耗ID,自增到最大后,报错提示读取自增ID失败:
/* SQL Error (1467): Failed to read auto-increment value from storage engine */

解决方案

  1. 一般来说表不应该存在这么大,在达到这么大之前就应该优化,例如,做分库分表之类的优化了。
  2. 调整数据类型,修改为BIGINT数据类型,但是要注意数据太多,DDL执行时长问题。(参考文末扩展内容)
    在这里插入图片描述
  3. 注意上层业务ORM框架的解析也要使用LONG数据类型

扩展

扩展1:修改字段的数据类型,建议使用modify 用法

1.修改字段的数据类型,建议使用modify 用法,更加友好;
modify 和change 区别:参考 https://stackoverflow.com/questions/14767174/modify-column-vs-change-column
在这里插入图片描述

# CHANGE
ALTER TABLE 
	`tb_id_incr`
CHANGE 
	COLUMN `id` `id` BIGINT NOT NULL AUTO_INCREMENT;
	
# MODIFY
ALTER TABLE
  `tb_id_incr`
MODIFY
  COLUMN `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT;

扩展2:Alter table的底层原理

  1. INPLACE模式和COPY复制临时表模式
    https://dev.mysql.com/doc/refman/5.7/en/alter-table.html
    在这里插入图片描述
  2. 修改数据类型使用的模式
    https://dev.mysql.com/doc/refman/5.7/en/innodb-online-ddl-operations.html
    可以看到 修改数据类型,只会使用COPY模式
    在这里插入图片描述
    修改过程,是会影响读写。
    列操作的影响

以上是关于MySQL中的自增主键 ID自增到最大,使用完id会发生什么,怎么办?的主要内容,如果未能解决你的问题,请参考以下文章

MySQL中的自增主键 ID自增到最大,使用完id会发生什么,怎么办?

Mysql对自增主键ID进行重新排序

mysql 批量插入 获取所有自增ID

关于 mysql 事务中的自增 id 的疑问

Mysql数据库表的自增主键重新排列

mysql自增主键怎么用