Sunskey

日拱一卒,不期而至

0%

MySQL 自增主键

自增主键为什么不是连续的

自增值的存储

表的自增值是保存在表结构定义里,表的结构定义放在后缀名为.frm的文件中,但是并不会保存自增值。

不同的引擎对于自增值的保存策略不同。

  • MyISAM引擎保存在数据文件中。
  • InnoDB引擎自增值,其实保存在了内存里。5.7版本以前会去寻找最大的max(id),放入内存中。而5.8以后则是记录在了redo log中。

自增值修改机制

  1. 如果插入数据时id字段指定为0、null或者未指定值、把就这个表当前的AUTO_INCREMENT值填到自增字段;
  2. 如果插入数据id字段指定了具体的值,就直接使用语句里指定的值。

假设,某次要插入的值是X,当前的自增值是Y。

  1. 如果X<Y,那么这个表的自增值不变;

  2. 如果X≥Y,需要把当前自增值修改为新的自增值。

新的自增值生成算法是:从auto_increment_offset 开始,以auto_increment_increment为步长,直到着到第一个大于X的值,作为新的自增值。

自增值的修改时机

自增数据的是在真正执行插入数据的操作之前。

自增主键id不连续的原因

1.唯一键冲突

2.事务的回滚

3.批量插入

InnoDB语句执行失败也不回退自增id。所以才只保证了自增id是递增的,但不保证是连续的。

自增锁优化

自增锁id并不是一个事务锁,而是每次申请完就马上释放。

对于批量插入数据的语句,MySQL有一个批量申请自增id的策略

1.语句执行过程中,第一次申请自增id,会分配1个;

2.1个用完以后,这个语句第二次申请自增id,会分配2个;

3.2个用完以后,这个语句第三次申请自增id,会分配4个;

4.依次类推,同一个语句去申请自增id,每次申请到的自增id个数都是上一次的两倍。

在生产上,尤其是有insert…select这种批量插入数据的场景时,从并发插入数据的角度考虑,建议设置

innodb_autoinc_lock_mode=2 ,并且 binlog_format=row.