Skip to content

面试速答(先看这里)

**一句话结论:**如果是我们自己显式定义的一个自增ID,如果已经达到了上限,那么下一次申请ID的时候,得到的值就是那个最大值,后续也不会再增加。

60秒标准回答:

我们知道,在MySQL中,自增主键有两种,一种是显式的、一种是隐式的。如果我们在一张表中没有定义主键,那么,MySQL会创建一个隐藏的主键(row_id)作为主键

那么,不管是我们自己定义的自增主键,还是row_id的这个主键,都是一个固定类型的,一般都是bigint unsigned,那么既然有固定类型,就有取值范围。那么随着数据量的增长,主键的值会不断增长, 那么万一超过了这个范围限制,会怎么样呢?

如果是我们自己显式定义的一个自增ID,如果已经达到了上限,那么下一次申请ID的时候,得到的值就是那个最大值,后续也不会再增加。这时候我们会拿到一个已经用过的主键,如果继续插入的话,会报主键冲突

**答题顺序:**结论 → 原理/机制 → 关键流程 → 场景与取舍 → 易错点

回答主线:

  • **要点1:**我们知道,在MySQL中,自增主键有两种,一种是显式的、一种是隐式的。
  • **要点2:**那么,不管是我们自己定义的自增主键,还是row_id的这个主键,都是一个固定类型的,一般都是bigint unsigned,那么既然有固定类型,就有取值范围。
  • **要点3:**那如果我们没有自定义自增ID,那么就会默认使用row_id,如果已经达到了上限,那么下一次申请ID的时候,得到的值会从0开始,然后继续重新自增。
  • **要点4:**那么,从这个方面来看的话,我们为了避免数据被覆盖,还是需要自己设置一个自增的主键ID的,毕竟异常我们是可以感知到的,但是数据覆盖我们可能过了很久才能发现。
  • **要点5:**MySQL中的自增主键用完是一个相对罕见的情况,但确实可能发生,尤其是在大数据量的应用中。

**记忆锚点:**row_id → MySQL → UUID → 归档旧数据(推荐) → unsigned → 都是一个固定类

关键取舍:

  • 那么随着数据量的增长,主键的值会不断增长, 那么万一超过了这个范围限制,会怎么样呢?
  • 但这会增加存储需求,并可能影响性能。

易错提醒:

  • 那么,从这个方面来看的话,我们为了避免数据被覆盖,还是需要自己设置一个自增的主键ID的,毕竟异常我们是可以感知到的,但是数据覆盖我们可能过了很久才能发现。

加分表达:

  • 如果我们在一张表中没有定义主键,那么,MySQL会创建一个隐藏的主键(row_id)作为主键。
  • 如果是我们自己显式定义的一个自增ID,如果已经达到了上限,那么下一次申请ID的时候,得到的值就是那个最大值,后续也不会再增加。
  • 这时候我们会拿到一个已经用过的主键,如果继续插入的话,会报主键冲突。

追问准备:

  • 围绕「row_id」:底层原理是什么?使用时有哪些边界和常见坑?
  • 围绕「MySQL」:底层原理是什么?使用时有哪些边界和常见坑?
  • 围绕「UUID」:底层原理是什么?使用时有哪些边界和常见坑?
  • 如果线上出现异常,你会如何定位、验证并规避?

典型回答 ​

我们知道,在MySQL中,自增主键有两种,一种是显式的、一种是隐式的。如果我们在一张表中没有定义主键,那么,MySQL会创建一个隐藏的主键(row_id)作为主键。

那么,不管是我们自己定义的自增主键,还是row_id的这个主键,都是一个固定类型的,一般都是bigint unsigned,那么既然有固定类型,就有取值范围。那么随着数据量的增长,主键的值会不断增长,那么万一超过了这个范围限制,会怎么样呢?

如果是我们自己显式定义的一个自增ID,如果已经达到了上限,那么下一次申请ID的时候,得到的值就是那个最大值,后续也不会再增加。这时候我们会拿到一个已经用过的主键,如果继续插入的话,会报主键冲突。

那如果我们没有自定义自增ID,那么就会默认使用row_id,如果已经达到了上限,那么下一次申请ID的时候,得到的值会从0开始,然后继续重新自增。但是,这种情况如果我们因为没有设置主键,所以他不会报主键冲突,他会直接把这个row_id = 0的数据插入到数据库中,并且会把之前的row_id=0的数据给直接覆盖了。

所以,结论是:

  • 显示自定义的自增ID,用完以后下次插入会报主键冲突。
  • 未定义自增ID主键,会用row_id,用完以后下一次插入会覆盖历史数据。

那么,从这个方面来看的话,我们为了避免数据被覆盖,还是需要自己设置一个自增的主键ID的,毕竟异常我们是可以感知到的,但是数据覆盖我们可能过了很久才能发现。

扩展知识 ​

真用完了咋办 ​

MySQL中的自增主键用完是一个相对罕见的情况,但确实可能发生,尤其是在大数据量的应用中。

一旦用完了,可以有以下几个解决方式:

  1. 重用未使用的主键值(不推荐):
  • 如果你的表中有删除操作,可能会有未使用的主键值。你可以通过编写脚本或程序来找到这些空缺,并在插入新行时显式地指定这些主键值。但这种方法可能会破坏数据的完整性和连续性。
  1. 归档旧数据(推荐):
  • 如果表中的一些数据是历史数据,不再经常访问,可以将其归档到另一个表中,然后从原表中删除这些数据。这可以为新数据释放主键空间。
  1. 使用UUID作为主键(不推荐):
  • 考虑使用 UUID(通用唯一标识符)作为主键。UUID 是128位长,几乎不可能用完。但这会增加存储需求,并可能影响性能。

📄 ✅uuid和自增id做主键哪个好,为什么?

打开文档:✅uuid和自增id做主键哪个好,为什么?