面试官:数据库自增ID用完了会怎么样?

摘要:
由于1,2数据已经存在,数据则是会被覆盖。总结自增ID达到上限用完了之后,分为两种情况:如果设置了主键,那么将会报错主键冲突。

看到这个问题,我想起当初玩魔兽世界的时候,25H难度的脑残吼的血量已经超过了21亿,所以那时候副本的BOSS都设计成了转阶段、回血的模式,因为魔兽的血量是int型,不能超过2^32大小。

估计暴雪的设计师都没想到几个资料片下来血量都超过int上限了,以至于大家猜想才会有后来的属性压缩。

这些都是题外话,只是告诉你数据量大了是有可能达到上限的而已,回到Mysql自增ID上限的问题,可以分为两个方面来说。

1.有主键

如果设置了主键,并且一般会把主键设置成自增。

我们知道,Mysql里int类型是4个字节,如果有符号位的话就是[-2^31,2^31-1],无符号位的话最大值就是2^32-1,也就是4294967295。

创建一张表试试:

CREATETABLE`test1`(
`id`int(11)NOTNULLAUTO_INCREMENT,
`name`varchar(32)NOTNULLDEFAULT'',
PRIMARYKEY(`id`)
)ENGINE=InnoDBAUTO_INCREMENT=2147483647DEFAULTCHARSET=utf8mb4;

然后执行插入

insertintotest1(name)values('qq');

这样表里就有一条达到有符号位的最大值上限的数据。

面试官:数据库自增ID用完了会怎么样?第1张

如果再次执行插入语句:

insertintotest1(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。

同样创建一张表作为测试:

CREATETABLE`test2`(
`name`varchar(32)NOTNULLDEFAULT''
)ENGINE=InnoDBDEFAULTCHARSET=utf8mb4;

通过ps -ef|grep mysql拿到mysql的进程ID,然后执行命令,通过gdb先把row_id修改为1

sudogdb-p2584-ex'pdict_sys->row_id=1'-batch

然后插入几条数据:

insertintotest2(name)values('1');
insertintotest2(name)values('2');
insertintotest2(name)values('3');

再次修改row_id为2^48,也就是281474976710656

sudogdb-p2584-ex'pdict_sys->row_id=281474976710656'-batch

再次插入数据

insertintotest2(name)values('4');
insertintotest2(name)values('5');
insertintotest2(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达到上限用完了之后,分为两种情况:

  1. 如果设置了主键,那么将会报错主键冲突。
  2. 如果没有设置主键,数据库则会帮我们自动生成一个全局的row_id,新数据会覆盖老数据

解决方案:

表尽可能都要设置主键,主键尽量使用bigint类型,21亿的上限还是有可能达到的,比如魔兽,虽然说row_id上限高达281万亿,但是覆盖数据显然是不可接受的。

- END -

免责声明:文章转载自《面试官:数据库自增ID用完了会怎么样?》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇基于pyqt的电子时钟用PHP和Python生成短链接服务的字符串ID下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

mysql之面试问题总结

问题1、char 与varchar的区别?        varchar是变长而char的长度是固定的。如果你的内容是固定的大小,char性能更好。       char[4] 与varchar[4]   存储字母a a占一个字符  varchar长度为4但是占此时为一个字符长度   而char则占4个字符 问题2、truncate 和delete 区别是...

MySQL是怎样运行的?打卡汇总

启动选项和系统变量 mysql配置方式之一,在命令行上使用选项配置。有长形式和短形式之分,同时等号=前后不能有空格。对于常用的选项提供短形式,也就是选项首字母前加‘-’前缀。这种方式只对当次启动有效。 mysql配置方式之二,在配置文件中使用选项。会按照一定路径寻找配置文件,ini,cnf都为配置文件。配置文件内容可以分组。可以通过命令行指定配置文件的优...

MySQL(一) 数据表数据库的基本操作

      序言         这类文章,记录我看《MySQL5.6从零开始学》这本书的过程,将自己觉得重要的东西记录一下,并有可能帮助到你们,在写的博文前几篇度会非常基础,只要动手敲,跟着我写的例子全部实现一遍,基本上就搞定了,前期很难理解的东西基本没有,所以写博文的内容,就是以练题的形式来呈现的。             需要用的资料以链接的形式给需...

EF里一对一、一对多、多对多关系的配置和级联删除

原文:EF里一对一、一对多、多对多关系的配置和级联删除 本章节开始了解EF的各种关系。如果你对EF里实体间的各种关系还不是很熟悉,可以看看我的思路,能帮你更快的理解。 I.实体间一对一的关系 添加一个PersonPhoto类,表示用户照片类 /// <summary> ///用户照片类 /// </summary>...

MySQL 千万 级数据量根据(索引)优化 查询 速度

一、索引的作用索引通俗来讲就相当于书的目录,当我们根据条件查询的时候,没有索引,便需要全表扫描,数据量少还可以,一旦数据量超过百万甚至千万,一条查询sql执行往往需要几十秒甚至更多,5秒以上就已经让人难以忍受了。 提升查询速度的方向一是提升硬件(内存、cpu、硬盘),二是在软件上优化(加索引、优化sql;优化sql不在本文阐述范围之内)。 能在软件上解决的...

使用Hibernate

1、Hibernate框架设计原理 1)设计原理 Hibernate采用ORM思想对JDBC进行封装,Hibernate框架是ORM思想的一种实现,解决对象和数据库数据映射问题 Hibernate提供一系列API,允许我们直接访问实体对象,然后根据ORM映射关系,转换成SQL去执行,从而达到访问数据库的目的。 2)ORM思想 ORM(ObjectRela...