自增主键的前世今生

引入:


使用MySQL建表时,我们通常会创建一个自增字段(AUTO_INCREMENT),并以此字段作为主键


本文将分三点阐述:

  1. 你可能不知道的自增主键
  2. 应对变化的自增主键
  3. [坑]如果自增主键用完怎么办

1.你可能不知道的自增主键

使用自增主键可以提高数据存储效率

在MySQL中(Innodb 存储引擎),数据记录本身被存于主索引(B+Tree)的叶子节点上
*补充:【要求同一个叶子节点内(大小为一个内存页或磁盘页)的各条数据记录按主键顺序存放】


针对索引,

  • 如果我们定义了主键(PRIMARY KEY),那么InnoDB会选择主键作为聚集索引
  • 如果没有显式定义主键,则InnoDB会选择第一个不包含有NULL值的唯一索引作为主键索引
  • 如果也没有这样的唯一索引,则InnoDB会选择内置6字节长的ROWID作为隐含的聚集索

*补充:【ROWID随着行记录的写入而主键递增,这个ROWID不像ORACLE的ROWID那样可引用,是隐含的】


Q:

每当有一条新的记录插入时,MySQL会根据其主键将其插入适当的节点和位置,如果页面达到装载因子(InnoDB默认为15/16),则开辟一个新的页(节点)。

A:

  • 如果表使用自增主键。每次插入新的记录,会顺序添加到当前索引节点的后续位置,一页写满,自动开辟一个新的页

  • 如果使用非自增主键(For Example:身份证号或学号等)【每次插入主键的值近似于随机】,每次新纪录都要被插到现有索引页中间某个位置,MySQL不得不为了将新记录插到合适位置而移动数据,甚至目标页面可能已经被回写到磁盘上而从缓存中清掉,此时又要从磁盘上读回来

    这增加了很多开销,同时频繁的移动、分页操作造成了大量的碎片,得到了不够紧凑的索引结构,后续不得不通过OPTIMIZE TABLE来重建表并优化填充页面。

自增id是增长的,不一定连续

原因有以下几点:

  • 唯一键冲突
  • 事务回滚
  • insert … select语句批量申请

针对自增值的保存策略:

InnoDB 引擎中,自增值保存在了内存中,继 MySQL 8.0 之后,出现了自增值持久化,自增值的变更记录存储在 redo log 中,重启时可以依靠其恢复之前的值

*补充:【自增值持久化:如果发生重启,表的自增值可以恢复为 MySQL 重启前的值】

2.应对变化的自增主键

导入:

在设计数据库时不需要费尽心思去考虑设置哪个字段为主键

但是应用到实际场景,自增主键的主要目的还是应对变化。

设计一个场景:

    维护商业账号的资质相关信息

最初设计: 账号是由全局唯一且自增的分布式ID生成器生成的,很显然这个时候我们把账号作为主键这就天然合理

业务迭代一定时间: 提出了新的需求,一个账号,在不同业务线,需要享有不同资质

比较: accountId 较之前不唯一,因为,同一个账号,不同业务线,资质是不一样的【无法像最初那样作为主键】

解决方式: 见场景中

3.如果自增主键用完怎么办

老掉牙但经典:【面试题】

面试官:“用过mysql吧,你们是用自增主键还是UUID?”
你:“用的是自增主键”
面试官:“为什么是自增主键?”
你:“因为采用自增主键,数据在物理结构上是顺序存储,性能最好,blabla…”
面试官:“那自增主键达到最大值了,用完了怎么办?”
你:“what,没复习啊!!”
( 然后,你就可以回去等通知了!)

说明: 自增 id 是整型字段,常用 int 类型来定义增长 id ,而 int 类型有上限 即增长 id 也是有上限的。

既然 int 不够了,首先想到的是改为 BigInt 类型【做个对比】

如果回答:把自增主键的类型改为BigInt类型就好了

面试官:“你在线上怎么修改列的数据类型的?”

修改方法:

  • 使用mysql5.6+提供的在线修改功能
  • 借助第三方工具
  • 改从库表结构,然后主从切换

差不多就算结束了这个问题了。但是回过头想一想,是不是一条路走到黑了,或许从头开始就错了呢!!!


插入一条生存力测试,形象生动:

  假如女朋友问:我刚才吃药时看窗外,你猜我看到了什么?

    歧途: 白云?你为什么不看我呢。

    正解: 你怎么要吃药呢


那么正解应该是什么呢?

这问题没遇到过,因为自增主键一般用int类型,一般达不到最大值,我们就分库分表了,所以不曾遇见过!

具体介绍…

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值