MySQL 的自增主键并不能保证一定是连续递增的。
自增值保存在哪里?
1)MyISAM 引擎的自增值保存在数据文件中
2)MySQL 5.x 版本的InnoDB存放在内存中,所以重启,会重新计算当前表中最大的主键值作为新的自增主键值
3) MySQL 8.0 版本后,自增值的变更记录被放在了 redo log 中,提供了自增值持久化的能力 ,也就是实现了“如果发生重启,表的自增值可以根据 redo log 恢复为 MySQL 重启前的值”
使用 insert into test_pk values(null, 1, 1) 插入一行数据,再执行 show create table 命令可以看到自增值AUTO_INCREMENT会增加(显示当前最新的自增值)
在 MySQL 里面,如果字段 id 被定义为 AUTO_INCREMENT,在插入一行数据的时候,自增值的行为如下:
- 如果插入数据时 id 字段指定为 0、null 或未指定值,那么就把这个表当前的 AUTO_INCREMENT 值填到自增字段;
- 如果插入数据时 id 字段指定了具体的值,就直接使用语句里指定的值。
- 自增值修改的这个操作,是在真正执行插入数据的操作之前。
自增值不连续的场景
- 插入指定自增字段值大于当前自增值
AUTO_INCREMENT+1,即跳过了一些数据 - 插入失败
- 插入后回滚(等价上面)
- 批量插入:insert ... select ,mysql每次申请两倍的id,多余的会浪费掉
- 如果是insert多组value,会计算value的数量申请足够的id,不会浪费
这里回滚不进行自增值的回滚,是因为多个事物插入的时候,自增值的回滚可能导致自增值异常 假设事务 A 申请到了 id = 1, 事务 B 申请到 id=2,那么这时候表 t 的自增值是 3,之后继续执行。这个时候 A 事物回滚如果自增值回滚会很麻烦
