01 前言
自增数据库 ID 用完怎么办?
其实这个问题可以分为两部分两种情况回答。
先上张脑图:
02 有主键
如果你的表有主键,并且把主键设置为自增。
在 MySQL 在中间,主键通常被设置为 int 型。而 MySQL 中 int 型占用 4 作为符号位,个字节的范围是 [-231,231-1,即[-2147483648,2147483647];如果没有符号位,最大值是 2^32-1,也就是 4294967295。
以下是一个符号位创建表:
CREATE TABLE IF NOT EXISTS `t`( `id` INT(11) NOT NULL AUTO_INCREMENT, `url` VARCHAR(64) NOT NULL, PRIMARY KEY ( `id` ) )ENGINE=InnoDB DEFAULT CHARSET=utf8; 复制代码
插入一个 id 为最大值 2147483647 如下图所示:
如果此时继续以下句子:
INSERT INTO t (url) VALUES ('wwww.javafish.top/article/erwt/spring') 复制代码
主要冲突会导致结果:
我在这里总结一线大厂Java面试题总结 学习思维导向各种知识点 一份300页pdf文档的Java总结核心知识点!
点击获取福利,扫描代码**备注[37]**可免费领取
2.1 解决方案
虽说 int 4 最大数据量存储个字节 21 1亿。你可能会觉得这么大的容量不应该用完。但在互联网时代,很有可能每天都会产生大量的数据。
因此,我们的解决方案是:。以这种方式存储的最大数据量是 2^64-1,我数不清有多少。反正你有生之年应该够了。
PS:。
03 没主键
另一种情况是。这种情况,InnoDB 它将自动帮助您创建一个不可见的长度 6 字节的 row_id,默认是无符号的,所以最大长度是 2^48-1。
实际上 InnoDB 保持全局 dictsys.row_id,所以。每次插入一个数据,全局 row_id 当成主键 id,然后全局 row_id 加 1。
1.创建一个没有显示设置主键的表 t:
CREATE TABLE IF NOT EXISTS `t`( `age` int(4) NOT NULL )ENGINE=InnoDB DEFAULT CHARSET=utf8; 复制代码
2、通过 ps -ef|grep mysql
命令获取 mysql 的进程 ID,然后执行命令,通过 gdb 先把 row_id 修改为 1。PS:没有 gdb 是的,百度安装
sudo gdb -p 16111 -ex 'p dict_sys->row_id=1' -batch 复制代码
下图是对的:
三、插入三个数据:
insert into t(age) values(1); insert into t(age) values(2); insert into t(age) values(3);
此时的数据库数据:
4、gdb 把 row_id 修改为最大值,28147497671066
sudo gdb -p 16111 -ex 'p dict_sys->row_id=281474976710656' -batch
5.插入三个数据:
insert into t(age) values(4); insert into t(age) values(5); insert into t(age) values(6);
此事数据库数据:
[外链图片存储失败,源站可能有防盗链机制,建议保存图片直接上传(img-koinr553-1651757265066)(https://upload-images.jianshu.io/upload_images/27952227-b5236bf2ce220b85.png?imageMogr2/auto-orient/strip|imageView2/2/w/1240)]
分析:
-
刚开始设置 row_id 为 插入三个数据 1、2、3 的 row_id 也理应是 1、2、3;没问题。
-
接着设置 row_id 为最大值,然后插入三个数据。此时数据库结果为:4、5、6、3;您会发现 1、2 被覆盖了。
-
row_id 在达到最大值后插入值 4、5、6 的 row_id 分别是 0、1、2;由于 row_id 为 1、2 因此,后者的值存在 5、6 会覆盖掉 row_id 为 1、2 的值。
结论:row_id 达到最大值后会从 0 重新开始计算;前插入的数据将被后插入的数据覆盖,不会报错。
04 总结
数据库自增主键用完后分为两种情况:
- 有主键,
- 无主键,InnDB 会自动生成全局row_id。在达到最大值后,它会从 0 开始计算,遇见 row_id 一样时,。所以,我们还是尽力吧。
除了上述解决方案外,我的回答还提到,在业务开发中,我们不会等到主键用完之日才分库分表,基本上不会遇到这种情况。
扫码**备注[37]**可免费领取