目录

MySQL 对自增值的保存策略

  • 在 MySQL 5.7 及之前的版本

    自增值保存在内存里,并没有持久化。每次重启后,第一次打开表的时候,都会去找自增值的最大值 max(id),然后将 max(id)+1 作为这个表当前的自增值。

    举例来说,如果一个表当前数据行里最大的 id 是 10,AUTO_INCREMENT=11。这时候,我们删除 id=10 的行,AUTO_INCREMENT 还是 11。但如果马上重启实例,重启后这个表的 AUTO_INCREMENT 就会变成 10。也就是说,MySQL 重启可能会修改一个表的 AUTO_INCREMENT 的值。

  • 在 MySQL 8.0 版本

    将自增值的变更记录在了 redo log 中,重启的时候依靠 redo log 恢复重启之前的值。

自增值修改机制

在 MySQL 里面,如果字段 id 被定义为 AUTO_INCREMENT,在插入一行数据的时候,自增值的行为如下:如果插入数据时 id 字段指定为 0、null 或未指定值,那么就把这个表当前的 AUTO_INCREMENT 值填到自增字段;如果插入数据时 id 字段指定了具体的值,就直接使用语句里指定的值。根据要插入的值和当前自增值的大小关系,自增值的变更结果也会有所不同。假设,某次要插入的值是 X,当前的自增值是 Y。

如果 X<Y,那么这个表的自增值不变;如果 X≥Y,就需要把当前自增值修改为新的自增值。

其他网友总结

在什么场景下自增主键可能不连续?

  • 1:唯一键冲突
  • 2:事务回滚
  • 3:自增主键的批量申请

深层次原因是,不判断自增主键是否已存在和减少加锁的时间范围和粒度->为了更高的性能->自增主键不能回退->自增主键不连续

自增主键是怎么做的唯一性的

自增值加1,自增锁控制并发

自增主键的生成性能如何

这个需要测试一下,数据库的自增主键也用做生成唯一数字,作为其他单号,比如:并发量小的订单号,性能可能一般。

自增主键有最大值吗?如果有,到了怎么办?

最大值应该有,因为数字总有个范围,到了当做字符串的一部分,然后再自增拼接上另一部分,貌似也可以。

自增主键的作用?保存机制?修改机制?

作用:让主键索引尽量地保持递增顺序插入,避免页分裂,使索引更紧凑。

保存机制:不同的存储引擎不一样。

  • MyISAM 引擎的自增值保存在数据文件中。

  • InnoDB 引擎的自增值,先是保存在了内存里,到了 MySQL 8.0 版本后,才有了“自增值持久化”的能力,放在了redolog里。

修改机制: 在 MySQL 里面,如果字段 id 被定义为 AUTO_INCREMENT,在插入一行数据的时候,自增值的行为如下:

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

根据要插入的值和当前自增值的大小关系,自增值的变更结果也会有所不同。假设,某次要插入的值是 X,当前的自增值是 Y。

  • 1:如果 X<Y,那么这个表的自增值不变;
  • 2:如果 X≥Y,就需要把当前自增值修改为新的自增值。

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