回答
自增 ID 指定义一个初始值,然后不停地往上加步长的数值字段。虽然自然数是没有上限的,但在计算机中会为字段定义类型,如
id int unsigned
,int 占四个字节,那么它就有上限了。对于自增 ID 用完了的场景需要根据实际情况来分析:有主键和无主键。
一、表定义的自增 id
当表定义的自增值达到上限后,再申请下一个 id 时,得到的值保持不变。故插入时会提升主键冲突错误。
create table t_test(
`id` int unsigned auto_increment,
`name` varchar(255) NOT NULL default '',
PRIMARY KEY (`id`)
) ENGINE=InnoDB,auto_increment=4294967295;
int 占四个字节,unsigned int 能到的最大值是 232-1(4294967295)。通常情况下是够用了,但在互联网业务频繁插入删除的表中可能会被用完。此时可以将主键 id 创建为 8 个字节的 unsigned bigint。
备注:单表 42 亿数据量也是惊人,老早就需要考虑分表了。
二、InnoDB 自增的 Row_id
另一种情况是建表时没有指定主键,那么 InnoDB 会创建一个不可见的,长度为 6 个字节的 row_id。InnoDB 内部维护**一个全局的 dict_sys.row_id 值,所有未定义主键的表都共享该 row_id(非单表独享),**每插入一行数据,当前的 dict_sys.row_id 值作为要插入数据的 row_id,并将 dict_sys.row_id 的值加1。row_id 具有如下特征:
- row_id 的值范围为 0 到 248 - 1。
- 当 dict_sys.row_id = 248 - 1,即 dict_sys.row_id 达到上限后,如果再有插入数据申请 row_id,下一个值就是0,如此循环。
- 在 InnoDB 中,申请到 row_id = N 后,会将这行数据写入表中;如果表中已经存在 row_id = N 的行,新写入的行就会覆盖原有的行。