面试官:数据库自增ID用完了会怎么样?
看到这个问题,我想起当初玩魔兽世界的时候,25H难度的脑残吼的血量已经超过了21亿,所以那时候副本的BOSS都设计成了转阶段、回血的模式,因为魔兽的血量是int型,不能超过2^32大小。
估计暴雪的设计师都没想到几个资料片下来血量都超过int上限了,以至于大家猜想才会有后来的属性压缩。
这些都是题外话,只是告诉你数据量大了是有可能达到上限的而已,回到Mysql自增ID上限的问题,可以分为两个方面来说。
1.有主键
如果设置了主键,并且一般会把主键设置成自增。
我们知道,Mysql里int类型是4个字节,如果有符号位的话就是[-2^31,2^31-1],无符号位的话最大值就是2^32-1,也就是4294967295。
创建一张表试试:
CREATE TABLE `test1` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
 `name` varchar(32) NOT NULL DEFAULT '',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2147483647 DEFAULT CHARSET=utf8mb4;
然后执行插入
insert into test1(name) values('qq');
这样表里就有一条达到有符号位的最大值上限的数据。

如果再次执行插入语句:
insert into test1(name) values('ww');
就会看到错误提示:1062 - Duplicate entry '2147483647' for key 'PRIMARY', Time: 0.000000s。
也就是说,如果设置了主键并且自增的话,达到自增主键上限就会报错重复的主键key。
解决方案,mysql主键改为bigint,也就是8个字节。
设计的时候要考虑清楚值的上限是多少,如果业务频繁插入的话,21亿的数字其实还是有可能达到的。
2.没有主键
如果没有设置主键的话,InnoDB则会自动帮你创建一个6个字节的row_id,由于row_id是无符号的,所以最大长度是2^48-1。
同样创建一张表作为测试:
CREATE TABLE `test2` (
 `name` varchar(32) NOT NULL DEFAULT ''
) ENGINE=InnoDB  DEFAULT CHARSET=utf8mb4;
通过ps -ef|grep mysql拿到mysql的进程ID,然后执行命令,通过gdb先把row_id修改为1
sudo gdb -p 2584 -ex 'p dict_sys->row_id=1' -batch
然后插入几条数据:
insert into test2(name) values('1');
insert into test2(name) values('2');
insert into test2(name) values('3');
再次修改row_id为2^48,也就是281474976710656
sudo gdb -p 2584 -ex 'p dict_sys->row_id=281474976710656' -batch
再次插入数据
insert into test2(name) values('4');
insert into test2(name) values('5');
insert into test2(name) values('6');
然后查询数据会发现3条数据是4,5,6,3。
因为我们先设置row_id=1开始,所以1,2,3的row_id也是1,2,3。
修改row_id为上限值之后,row_id会从0重新开始计算,所以4,5,6的row_id就是0,1,2。
由于1,2数据已经存在,数据则是会被覆盖。
总结
自增ID达到上限用完了之后,分为两种情况:
- 如果设置了主键,那么将会报错主键冲突。
- 如果没有设置主键,数据库则会帮我们自动生成一个全局的row_id,新数据会覆盖老数据
解决方案:
表尽可能都要设置主键,主键尽量使用bigint类型,21亿的上限还是有可能达到的,比如魔兽,虽然说row_id上限高达281万亿,但是覆盖数据显然是不可接受的。
- END -
面试官:数据库自增ID用完了会怎么样?的更多相关文章
- 分库分表数据库自增 id
		分库分表之后,ID 主键如何处理? 面试题 分库分表之后,id 主键如何处理? 面试官心理分析 其实这是分库分表之后你必然要面对的一个问题,就是 id 咋生成?因为要是分成多个表之后,每个表都是从 1 ... 
- mysql 数据库自增id 的总结
		有一个表StuInfo,里面只有两列 StuID,StuName其中StuID是int型,主键,自增列.现在我要插入数据,让他自动的向上增长,insert into StuInfo(StuID,Stu ... 
- 解决数据库自增ID的问题
		(1)设置主键自增为何不可取这样的话,数据库本身是单点,不可拆库,因为id会重复. (2)依赖数据库自增机制达到全局ID唯一使用如下语句:REPLACE INTO Tickets64 (stub) V ... 
- 分布式ID系列(3)——数据库自增ID机制适合做分布式ID吗
		数据库自增ID机制原理介绍 在分布式里面,数据库的自增ID机制的主要原理是:数据库自增ID和mysql数据库的replace_into()函数实现的.这里的replace数据库自增ID和mysql数据 ... 
- mysql数据库表自增ID批量清零   AUTO_INCREMENT = 0
		mysql数据库表自增ID批量清零 AUTO_INCREMENT = 0 #将数据库表自增ID批量清零 SELECT CONCAT( 'ALTER TABLE ', TABLE_NAME, ' AUT ... 
- mybatis获取数据库自增id
		http://blog.csdn.net/dyllove98/article/details/8866357 http://www.iteye.com/problems/86864 insert标签中 ... 
- MySQL 的自增 ID 用完了,怎么办?
		一.简述 在 MySQL 中用很多类型的自增 ID,每个自增 ID 都设置了初始值.一般情况下初始值都是从 0 开始,然后按照一定的步长增加.在 MySQL 中只要定义了这个数的字节长度,那么就会 ... 
- mysql数据库自增id重新从1排序的两种方法
		mysql默认自增ID是从1开始了,但当我们如果有插入表或使用delete删除id之后ID就会不会从1开始了哦. 使用mysql时,通常表中会有一个自增的id字段,但当我们想将表中的数据清空重新添 ... 
- MySQL的自增ID用完了,怎么办?
		既然这块知识点不清楚,那回头就自己动手实践下. 首先,创建一个最简单的表,只包含一个自增id,并插入一条数据. create table t0(id int unsigned auto_increme ... 
随机推荐
- moviepy音视频剪辑:视频变换处理与内容相关的变换函数headblur、mask_and/or、mirror_x/y、rotate、painting、scroll介绍
			一.引言 在<moviepy音视频剪辑:moviepy中的剪辑基类Clip详解>介绍了剪辑基类的fl.fl_time.fx方法,在<moviepy音视频剪辑:视频剪辑基类VideoC ... 
- 第9.4节 Python中用readline读取二进制文件方式打开文件
			在<第9.3节 Python的文件内容读取:readline>中介绍了使用readline读取文件的处理,readline除了使用文本文件方式打开文件读外,也可以读取二进制方式打开的文件, ... 
- 分布式计算框架-Spark(spark环境搭建、生态环境、运行架构)
			Spark涉及的几个概念:RDD:Resilient Distributed Dataset(弹性分布数据集).DAG:Direct Acyclic Graph(有向无环图).SparkContext ... 
- js- 对象的连续调用
			var jack = { somke : function (){ console.log('I was in the somkeing...cool..'); return this; }, dri ... 
- 【面试题】GC Root都有哪些?
			那天去面试,面试官问我JVM垃圾回收,我是有备而来,上来就是一个可达性分析算法,然后就是一个复制算法,标记-清理,标记-整理,以及几个常见的垃圾回收器 详情见:https://www.cnblogs. ... 
- dataframe 检查缺失值
			s = df.isnull().any() #返回series形式,可以用enumerate打印s #true代表有空值 null_index = [] for i,j in enumerate(s) ... 
- 使用Promise实现红绿灯交替重复亮
			红灯3秒亮一次,黄灯2秒亮一次,绿灯1秒亮一次:如何让三个灯不断交替重复亮灯?(用Promise实现) function red() { console.log('red'); } function ... 
- jQuery插件的2种类型
			1.封装方法插件 封装方法插件在本质上来说,是一个对象级别的插件,这类插件首先通过jQuery选择器获取对象,并为对象添加方法,然后,将方法进行打包,封闭成一个插件,这种类型的插件编写简单,极易调用 ... 
- UOJ61. 【UR #5】怎样更有力气
			题目链接 Statement 给定一棵 \(n\) 点树 \(T\) 和 \(m\) 个操作 v u w : 在 \(T\) 中 \(u,v\) 的最短路上所有点里面选出若干对(可以不选,可以重复), ... 
- 题解-洛谷P5217 贫穷
			洛谷P5217 贫穷 给定长度为 \(n\) 的初始文本 \(s\),有 \(m\) 个如下操作: \(\texttt{I x c}\),在第 \(x\) 个字母后面插入一个 \(c\). \(\te ... 
