mysql 8.0 中 innodb 自增计数器通过新增 redo 日志类型 mlog_table_dynamic_meta 持久化,insert 或 alter table 设置 auto_increment 时写入该日志,由 checkpoint 批量刷入系统表;update/delete 不触发;重启时从 redo log 重放并结合 max(id) 确定新起点。

MySQL 8.0 中 InnoDB 的自增计数器不再丢失,是因为它被真正写进了 redo log,而不是只存在内存里。
自增值怎么进 redo log 的?
MySQL 8.0 引入了新的 redo 日志类型 MLOG_TABLE_DYNAMIC_META,专门记录元数据变更。每次自增计数器更新(比如 INSERT 或 ALTER TABLE t AUTO_INCREMENT = N),InnoDB 就会生成一条该类型的日志,把新值落盘。
- 不是每次递增都立刻刷磁盘,而是先记日志,再由 checkpoint 机制批量持久化到系统表(如
mysql.innodb_table_stats) -
UPDATE或DELETE不触发计数器变化,也就不会写这条日志 - 事务回滚不影响已分配的自增值——
redo log里存的是“已成功分配并进入引擎层”的值,不是“预分配”或“未提交”的值
为什么 SHOW CREATE TABLE 看到的值有时不准?
SHOW CREATE TABLE 返回的 AUTO_INCREMENT=xxx 是内存字典缓存的快照,不是磁盘权威值。高并发插入后还没触发 checkpoint,这个值可能滞后于 redo log 里最新已分配的值。
- 真正可靠的方式是:
SELECT AUTO_INCREMENT FROM information_schema.TABLES WHERE TABLE_SCHEMA='db_name' AND TABLE_NAME='tbl_name' - 这个查询由 server 层发起,读取的是与崩溃恢复逻辑一致的数据字典状态
-
information_schema.tables.auto_increment视图有严重缓存延迟,重启后可能几分钟都不刷新,完全不可信 -
SELECT MAX(id)只反映当前数据最大值,和计数器无关;ANALYZE TABLE对自增值无任何影响
重启后值怎么恢复出来的?
MySQL 启动时会重放 redo log,从中提取最后一次成功的自增计数器值,再跟表中当前 MAX(id) 比较,取较大者加步长作为新起点。
- 比如
redo log记着AUTO_INCREMENT=5000,而表里MAX(id)=4999→ 新值就是 5000 - 如果表里
MAX(id)=5002→ 新值就是 5003 - 哪怕删光所有数据,只要之前分配过 id=10000,重启后仍从 10001 开始,不会退回到 1
- 这个机制仅对 InnoDB 生效,MyISAM 仍走老路(查文件头),但基本不用了
最易被忽略的一点:手动执行 ALTER TABLE t AUTO_INCREMENT = N 在 8.0 中是真正持久化的,但在 5.7 中只改内存,重启即失效。如果你在升级后还按旧经验判断自增值,大概率会误判主键冲突风险或业务幂等逻辑。











