mysql 8.0并未解决自增id断层问题,反而通过redo log持久化使断层固化:已分配未提交的id不回退,重启后取max(id)与redo中最大已分配值的较大者加步长,导致空洞不可修复。

没有解决断层问题,反而让断层更“坐实”了。
事务回滚后自增ID仍递增,是InnoDB的主动设计
事务回滚时,AUTO_INCREMENT值不会回退,这不是bug,而是性能取舍。InnoDB在执行INSERT语句时,**立刻分配并写入redo log**,这个动作不依赖事务是否提交。一旦分配,就不可逆。
- 回滚需要额外加锁、校验、补偿,高并发下会严重拖慢写入吞吐
- MySQL 8.0 的持久化机制(redo log + 数据字典)只是把“已分配的最大值”存下来,不是存“可用最小值”
- 所以回滚造成的ID空洞(比如分配了100但回滚了),重启后依然保留——因为100已被记入redo,且大于表中当前
MAX(id)
所谓“解决”,其实是解决了重启导致的“意外回退”,不是解决断层
MySQL 5.7及之前,重启后会查MAX(id)重新初始化计数器,可能把“浪费掉的ID”又捡回来(比如删光数据后重启,AUTO_INCREMENT变回1)。这看起来像是“修复断层”,实则是掩盖问题。
- MySQL 8.0 持久化后,重启时取
MAX(id)和 redo log 中记录的已分配值二者较大者 + 步长 - 这意味着:只要曾经分配过10000,哪怕全删光、重启多次,下次插入仍是10001(步长=1)
- 断层被固化,不再因重启而“偶然修复”
show create table 显示的 AUTO_INCREMENT 值不准,别拿它判断断层
执行SHOW CREATE TABLE看到的AUTO_INCREMENT=xxx是内存快照,不是权威值。它更新滞后,尤其在刚回滚或并发插入后。
- 真正反映当前生效逻辑的是:重启后第一次插入时实际分配的ID
- 想验证是否“断层”,直接
INSERT一条再SELECT,不要看information_schema.TABLES.auto_increment——那个字段在8.0里已不参与一致性保障 - 如果业务强依赖连续ID,必须放弃
AUTO_INCREMENT,改用应用层序列或UUID+业务ID组合
断层从来不是故障,而是InnoDB为并发与崩溃恢复做的权衡。8.0的持久化没消除它,只是让它变得可预期、不可绕过——这点最容易被误读成“修复”。











