MySQL 自增主键一定是连续的吗?
2024年7月2日大约 2 分钟MySQL
MySQL 自增主键一定是连续的吗?
自增主键的特点就是
当表中新增一条记录时,主键值会根据自增步长自动叠加,通常会将自增步长设置为 1,也就是说自增主键值是连续的
自增值存储机制
- 在 MySQL 5.7 以及之前的版本,自增值保存在内存里
每次重启后,第一次打开表的时候,都会去找自增值的最大值max (id)
,然后将max (id) + 1
作为这个表当前的自增值 - 在 MySQL 8.0 版本,将自增值的变更记录在了
redo log
中,重启的时候依靠redo log
恢复重启之前的值
导致自增值不连续的原因
当前, Table A 的 Col B 存在唯一键约束,并且已经存了一条 B=3 的记录了
- 唯一键冲突
此时我们继续插入 B=3 的记录,就会出现唯一键冲突插入报错
但是插入报错并不会将自增值改回去,此时的自增值已经 +1 了,下次插入新值时,对应的 ID 也是自增后的自增值
自增字段值的生成是由存储引擎生成的,而不是优化器完成的,因此,在执行 SQL 语句时,即使未指定自增字段列,也不会对性能产生任何影响
事务回滚
很好理解
开启一个事务,并插入 B=4 的记录(此时 id 应该为 4),然后进行回滚
回滚后重新插入 B=4 的记录,此时 ID 为 5批量插入数据
MySQL 在批量插入数据时,会去批量申请 id
而批量申请 id 的一个策略便是
在同一条语句中
- 第一次申请,会分配 1 个
- 第二次申请,会分配 2 个
- 第三次申请,会分配 4 个
- 第 n 次申请,会申请 2 的 n-1 次方个
比如现在有一张新表 Table A,批量插入 5 条数据
那么,在申请 id 时,MySQL 会先申请 1 个,不够,再申请 2 个,还是不够,再申请 4 个,终于够了
5 条新数据,但是自增 id 用了 7 个
所以,在下一次插入新数据时,自增 id 是从 8 开始的