当前位置: 首页 > 科技观察

面试官:MySQL自增长ID用完了怎么办?这是我见过最中肯的回答

时间:2023-03-23 12:05:49 科技观察

MySQL已用完自增ID。我应该怎么办?作为一名程序员,不知道你在求职面试的时候有没有遇到过类似的问题。张工是一名java程序员。他最近去一家互联网公司面试,面试官问了他这样一个问题。面试官:“你用过mysql吗?你数据表的主键id是用自增主键还是UUID?”张工:“使用自增主键”面试官:“为什么要自增主键?”张工:“因为采用了自增主键,数据在物理结构上是顺序存储的,性能好。”面试官:“自增主键已经达到最大值,用完了怎么办?”面试官:“你可以回去等通知。”今天就来说说吧。自增主键用完了怎么办?在mysql中,int整数的范围如下:int的取值范围为:-2^31——2^31-1,即-2147483648—2147483647如图:以无符号整数为例,存储范围为0到4294967295,约43亿。当自增id达到最大值后,继续插入会怎样,我们来练习一下。首先创建一个表tb_user,表中只包含一个自增idcreatetabletb_user(idintunsignedauto_incrementprimarykey);然后向该表中插入一条数据:insertintotb_uservalues(null);通过show命令showcreatetabletb_user;查看表情况:CREATETABLE`tb_user`(`id`int(10)unsignedNOTNULLAUTO_INCREMENT,PRIMARYKEY(`id`))ENGINE=InnoDBAUTO_INCREMENT=2DEFAULTCHARSET=utf8细心的你会发现AUTO_INCREMENT已经有了变成了2,但是这个距离最大值4294967295还差得很远,要变成4294967295,需要插入很多条记录。其实并没有那么麻烦。我们可以在建表的时候直接声明AUTO_INCREMENT的初始值。调整刚才的建表语句,先删除刚才的表,然后在建表的时候加上auto_increment=4294967295createtabletb_user(idintunsignedauto_incrementprimarykey)auto_increment=4294967295;然后在表中插入一条记录insertintotb_uservalues(null);同样,我们使用show命令查看表tb_user的表结构:CREATETABLE`tb_user`(`id`int(10)unsignedNOTNULLAUTO_INCREMENT,PRIMARYKEY(`id`))ENGINE=InnoDBAUTO_INCREMENT=4294967295DEFAULTCHARSET=utf8通过select*fromtb_user,我们发现id是4294967295,已经是最大值了。这时候,如果我们尝试往表中插入一条数据,就会报如下所示的主键冲突异常。[SQL]insertintotb_uservalues(null);[Err]1062-Duplicateentry'4294967295'forkey'PRIMARY'这说明再次插入时,使用的自增ID还是4294967295,主键冲突异常会被举报的。4294967295,这个号码已经可以应付大部分场景了,如果你的服务频繁插入删除数据,还是有用完的风险。推荐使用bigintunsigned,这个数字会很大。那有什么办法解决呢?答案是肯定的,解决方法也很简单。将Int类型更改为BigInt类型。BigInt的取值范围如下-2^63-1到2^63-1-92233720368547758089223372036854775807即使每秒发送数据向表中插入10000条数据并运行100年。让我们看看有多少数据。给BigInt类型加上ID就可以解决问题。如果你在面试中这样回答面试官。你:“不容易啊,把自增主键的类型改成BigInt类型就好了!”面试官:“如何在线更改列的数据类型?”你:“altertabletb_userchangeididbigint;”面试官:“你有实际操作经验吗?”你:“……没有实际操作。”需要注意的是,该方法只在myl5.6+支持,mysql支持在线修改数据库表。在修改表的过程中,对于大多数操作,可以读取或写入原始表。对于修改数据类型的操作,不支持并发DML操作!也就是说,如果直接使用alter等语句在线修改表的数据结构,这张表将无法进行更新操作(delete、update、insert)。因此,在生产线上实施修改表结构等计划是不可行的。有没有更好的办法?我们稍后会讨论这个问题。不知道大家有没有注意到这样的情况。虽然主键自增ID是从0开始的,也就是说现在可以使用的范围是0~2147483647,但是实际数据中有些id值是不连续的。如果实际生产表中有单表上亿条数据,此时如果要往数据表中写入数据,性能肯定会受到影响,必须赶紧考虑分库分库桌子。一旦数据库分表,我们就不能依赖每张表的自增id来全局唯一标识这些数据。此时,我们需要提供一个全局唯一的id号生成策略来支持分库分表的环境。所以实际中不可能等到自增主键用完。更友好的回答,不妨参考这样一个面试官:“自增主键已经达到最大值,用完了怎么办?”你:没遇到过这个问题,因为自增主键我们用的是int类型,一般不能达到最大值。值,就要考虑分表分库。如果面试官有追求,继续问你分库分表的重点,你可以有针对性的回答,说明你在这方面有充分的开发经验,相信会加分的到这次采访。总结:mysql数据库表的自增ID达到上限后,此时再申请它的值是不会改变的。如果继续插入数据,会导致主键冲突异常。因此,在设计数据字典时,需要根据业务的需要选择合适的字段类型。