思考
我们一般日常在建立一个表时会为其建立一个自增主键id。主键id可以tinyint、smallint、int、bigint。 然而大家有没有想过如果自增id用完了咋办?
实战
CREATE TABLE `test` (
`id` tinyint unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(255) not null default "",
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4;
- 建立一个主键id是无符号的tinyint型的test表,我们知道对于unsigned tinyint来说最大的值是255
mysql> INSERT INTO `test` (`id`,`name`) VALUES (255,'t1');
Query OK, 1 row affected (0.00 sec)
- 我们先插入一条数据并且把最大的id占用了,然后再插入一条数据看看:
mysql> INSERT INTO `test` (`name`) VALUES ('t2');
ERROR 1062 (23000): Duplicate entry '255' for key 'PRIMARY'
可以发现报错了,所以结论是:当自增id用完了就会报错?先别急接着看。
没有主键
我们知道mysql其实可以不用创建带主键的表。当没有主键时,mysql会为我们创建一个隐藏的自增id row_id
- row_id是全局共享的,并不是单表独有的
- row_id 是占6个字节,所以row_id最大是2^48-1=281474976710655
- 当row_id用完之后,下一个插入的数据并不会报主键冲突,而是会覆盖,并且row_id是从0开始的
- 假设现在row_id 从 0~2^48-1 都被占有
- 此时再插入一条数据
可以发现第一条数据会被覆盖。
- 会发现开始的那条数据会被覆盖第一条数据。
总结
- 有主键的时候,当id用完时,会报写冲突错误
- 无主键的时候,当id用完时,会从0开始覆盖老数据
欢迎大家关注公众号《假装懂编程》,我将持续输出网络、数据库、go、缓存、架构、面试、程序人生相关文章。