MySQL的自增主键

查看自增主键值:

show create table指令中查到的AUTO_INCREMENT值就是下一次要插入的数据行的主键值。

自增主键的持久化

MySQL8.0之后会将自增主键进行持久化(写入redo log),所以数据库重启后,可以接着表中当前数据行后继续插入自增主键。

自增主键的计算方法

当用户没有指定插入数据行的主键id时,系统默认用AUTO_INCREMENT的值。
当用户指定了插入数据行的主键id时,就不用MySQL默认计算得到的AUTO_INCREMENT值,(插入数据后系统会重新计算下一个默认的自增主键值,有两种情况),可以结合下图:

  1. 用户插入的数据行主键id小于AUTO_INCREMENT,那么下次默认插入的id值仍为AUTO_INCREMENT值。
  2. 用户插入的数据行id大于当前默认的AUTO_INCREMENT,会重新根据策略计算下一个默认值。(从自增主键的初始值开始按照自增步长找到第一个大于当前最大主键id的值作为新的AUTO_INCREMENT)

请添加图片描述

自增主键的线程安全

多事务并发时,MySQL会给自增主键加锁,不同事务在执行sql语句前先要获取主键锁,然后得到最新的主键id,再占据该id对应的数据行,最后判断sql语句是否合理,合理就在该行插入数据,否则该行只有主键id,其他字段为空(不会释放该行的空间)。

异常情况:自增步长默认为一却不连续递增?

按照上述逻辑,当采取的自增主键的步长为1时,有时候并不是在当前最大的id基础上加一作为下一个AUTO_INCREMENT,即AUTO[i+1] != AUTO[i] + 1

可能发生该种情况的场景

  1. 插入数据的唯一索引值冲突,插入数据失败(唯一索引字段已经存在要插入的值);
  2. 多事务并发时,某些事务回滚,数据行中只有主键id值(已经获得主键锁,并占据该行);
  3. 自增主键批量申请(为了提高多事务并发获取主键锁的速度,每一次MySQL会多发几个主键id给事务,类似于MySQL的磁盘预读机制,并不是执行一条sql前请求一次主键锁),最后会存在没有用完的id。

原因

每次当要执行sql语句插入数据前,MySQL会计算默认要插入的数据行的主键id,然后占据数据表中这行数据,最后判断sql语句的逻辑是否可以插入数据,这时候如果sql语句逻辑错误(对应场景1,2),无法插入表中,那么这就会造成该行只有主键id,没有其他字段值(场景3也包含在内)。而下一次插入新的语句就会在该行id的基础上继续递增主键id值,就出现了不连续的自增+1主键。

ps: MySQL之所以不设置插入语句失败时自增主键id回退,是为了提高事务并发时的效率。(如果可以回退,事务回滚时下次插入数据就要进行新生成的AUTO_INCREMENT是否已被其他事务占用的复杂判断过程)

参考文章:

https://time.geekbang.org/column/article/80531

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值