MySQL中innodb引擎中自增主键为什么不是连续的?

版本区别

MySQL5.7以及之前的版本中自增主值是保存在内存中的,并没有持久化,每次重启之后第一次打开表的时候汇去找自增值的最大值max(ID),然后进行+1操作后作为当前表的自增值。

而在MySQL8.0的版本后,MySQL有了“自增值持久化”的能力,实现了MySQL重启后可以恢复为重启之前的值。8.0版本将自增值的变更记录在redo log 中,重启的时候依靠redo log恢复之前的值。

导致自增主键不连续的原因
  1. 唯一键冲突会导致自增主键id不连续
    插入一条数据时先获取自增值,这是自增值会+1,当插入失败的时候,自增值不会回退
  2. 事务回滚也会导致自增主键id不连续
    和唯一键冲突同样的道理
为什么自增值不能回退

假设有两个并行执行的事务,为了避免两个事务申请到相同的自增值,肯定需要加锁,然后顺序申请:

  • 假设事务一申请到了id=1,而事务二申请到了id=2,此时自增值的值为3,然后继续执行
  • 如果事务二正确提交了,而事务一出现了唯一键冲突
  • 如果允许事务一回退自增id,那么就会出现表中已经存在id=2的记录,而当前的自增id值为1
  • 当继续执行其他的事务就会申请到id=2,此时会出现插入语句报错“主键冲突”

有两种方式解决这个主键冲突

  1. 每次申请id之前,判断表中是否已经存在这个id,如果存在,则跳过这个id,当然这样的效率不高
  2. 扩大自增id的锁范围,必须等一个事务执行完成并提交,下一个事务才可以再申请id,这样会导致系统并发能力下降。

可见,无论如何都会导致性能问题,所以innodb只能保证自增id是递增的,但不保证是连续的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值