mysql自增长id用完了,怎么办?

mysql自增长id用完了,怎么办?
在mysql,int整型的范围如下int的取值范围为:-2^31——2^31-1,即-2147483648—2147483647
 
如图:
 
以无符号整型为例,存储范围为0——4294967295,约43亿。当自增id达到最大值时,这是继续插入会出现什么异常呢,
 
我们来动手实践下。
 
首先,创建一张表tb_user,这张表只包含一个自增id
 
create table  tb_user(id int unsigned auto_increment primary key) ;
 
然后向这张表插入一条数据:
 
insert into tb_user values(null);
 
通过show命令show create table tb_user;查看表情况:
 
CREATE TABLE ——tb_user—— (
 
  ——id—— int(10) unsigned NOT NULL AUTO_INCREMENT,
 
  PRIMARY KEY (——id——)
 
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8
 
细心的你会发现 AUTO_INCREMENT 已经变成2,不过这离最大值4294967295远着呢,要想让它变成4294967295得插入非常多的记录,其实不用这么麻烦,我们可以在创建表的时候,直接声明AUTO_INCREMENT的初始值。
 
把我们刚才的创建表语句调整下,先把刚才的表删除掉,然后在创建表时加上auto_increment = 4294967295
 
create table tb_user(id int unsigned auto_increment primary key) auto_increment = 4294967295;
 
 然后同样往表插入一条记录
 
insert into tb_user values(null);
 
同样,我们通过show命令,查看表tb_user的表结构:
 
CREATE TABLE ——tb_user—— (
 
  ——id—— int(10) unsigned NOT NULL AUTO_INCREMENT,
 
  PRIMARY KEY (——id——)
 
) ENGINE=InnoDB AUTO_INCREMENT=4294967295 DEFAULT CHARSET=utf8
 
通过
 
select * from tb_user
 
我们查询到id 为4294967295,已经是最大值,这时候如果再
 
当想往表在尝试插入一条数据时,报一个主键冲突异常如下所示。
 
[SQL]insert into tb_user values(null);
 
[Err] 1062 - Duplicate entry '4294967295' for key 'PRIMARY'
 
这可以说明,当再次插入时,使用的自增ID还是4294967295,就会报主键冲突的异常了。
 
4294967295,这个数字已经可以应付大部分的场景了,如果你的服务会经常性的插入和删除数据的话,还是存在用完的风险。
 
建议采用bigint unsigned,这个数字就大了。
 
那有什么办法解决,答案是肯定的,解决方法也是很简单的,将Int类型改为BigInt类型,BigInt的范围如下
 
-2^63-1到2^63-1
 
-9223372036854775808  9223372036854775807
 
就算每秒往数据表插入10000条数据,运行100年,来看看数据量有多少
 
10000*24*3600*365*100=31536000000000
 
这数字距离BigInt的上限还差的远,因此你将自增ID设为BigInt类型,就可以解决问题了。
 
如果你在面试中是这样回答面试官的。
 
你:"这还不简单,把自增主键的类型改为BigInt类型就可以解决了!"
 
面试官:"你在线上怎么修改列的数据类型的?"   
 
你:"alter table tb_user change id  id bigint;"
 
面试官:“你有实际操作经验吗?”
 
你:“……没有实际操作过”
 
需要注意的是,这种方式在myl5.6+才开始支持,mysql支持在线修改数据库表,在修改表的过程中,对绝大部分操作,原表可读,也可以写。
 
对于修改数据类型这种操作,是不支持并发的DML操作!也就是说,如果你直接使用alter这样的语句在线修改表数据结构,会导致这张表无法进行更新类操作(delete、update、insert)。所以,想在生产线上执行修改表结构这样的方案是不可行的。
 
那有没有更好的方式,对于这个问题,我们以后再做讨论。
 
不知你有没有留意到这样一种情况,虽然主键自增ID是从0开始的,也就是说,现在可以用的范围为0——2147483647,但实际数据中有些id的值并不是连续的。
 
要是实际生产表出现单表超过上亿的数据量了,这时候想再往数据表写数据,性能肯定是受影响了,得赶紧考虑分库分表了。
 
一旦分库分表了,我们就不能依赖于每个表的自增id来全局唯一标识这些数据了。此时,我们就需要提供一 个全局唯一的id号生成策略来支持分库分表的环境。
 
所以在实际中,根本等不到自增主键用完的情况。
 
较友好的回答不妨参考这样的
 
面试官:"那自增主键达到最大值了,用完了怎么办?"   
 
你:这问题没遇到过,因为自增主键我们用int类型,一般达不到最大值,就要考虑分表分库了。
 
要是面试官穷追不舍,继续问你有关分库分表的要点,你也就可以针对性地回答,说明你完全有这方面的开发经验,相信能为这次面试加分。
 
总结:
 
mysql数据库表的自增 ID 达到上限之后,这时候再申请它的值就不会在改变了,如果继续插入数据就会导致报主键冲突异常。
 
因此在做数据字典设计时,要根据业务的需求来选择合适的字段类型。
 
由于笔者知识及水平有限,文中错漏之处在所难免,如有不足之处,欢迎交流。

推荐阅读