![MySQL 8从入门到精通(视频教学版)](https://wfqqreader-1252317822.image.myqcloud.com/cover/737/26542737/b_26542737.jpg)
上QQ阅读APP看书,第一时间看更新
4.6 MySQL 8.0的新特性2——自增变量的持久化
在MySQL 8.0之前,自增主键AUTO_INCREMENT的值如果大于max(primary key)+1,在MySQL重启后,会重置AUTO_INCREMENT=max(primary key)+1,这种现象在某些情况下会导致业务主键冲突或者其他难以发现的问题。
下面通过案例来对比不同的版本中自增变量是否持久化。
在MySQL 5.7版本中,测试步骤如下:
创建的数据表中包含自增主键的id字段,语句如下:
![](https://epubservercos.yuewen.com/76103A/15056702904172406/epubprivate/OEBPS/Images/1083.jpg?sign=1739021313-CyP4yRAfhwjqggCy7QjK8EpVtadQNmoA-0-ddfffcc46cd66064cba98a74d90cc757)
插入4个空值,执行如下:
![](https://epubservercos.yuewen.com/76103A/15056702904172406/epubprivate/OEBPS/Images/1084.jpg?sign=1739021313-3Bazca0bNCHat58SeP95XQdwzhVYijQY-0-00cdbf4e6342a618f43ca3dc5198edc4)
查询数据表test1中的数据,结果如下:
![](https://epubservercos.yuewen.com/76103A/15056702904172406/epubprivate/OEBPS/Images/1085.jpg?sign=1739021313-VR0YqZTJhoBwXD8zaarmmBHVr6EUIxsQ-0-f99d5ab69573a4308627209b6ff5461e)
删除id为4的记录,语句如下:
mysql> DELETE FROM test1 where id=4; Query OK, 1 row affected (0.04 sec)
再次插入一个空值,语句如下:
mysql> INSERT INTO test1 values(0); Query OK, 1 row affected (0.03 sec)
查询此时数据表test1中的数据,结果如下:
![](https://epubservercos.yuewen.com/76103A/15056702904172406/epubprivate/OEBPS/Images/1086.jpg?sign=1739021313-mtHNM3ggp1OBfXEE1YKI0dTq6Xk1OpUS-0-42a8deeb0928c317a9ae5a629a5e4947)
从结果可以看出,虽然删除了id为4的记录,但是再次插入空值时,并没有重用被删除的4,而是分配了5。
删除id为5的记录,结果如下:
mysql> DELETE FROM test1 where id=5; Query OK, 1 row affected (0.04 sec)
重启数据库,重新插入一个空值。
mysql> INSERT INTO test1 values(0); Query OK, 1 row affected (0.02 sec)
再次查询数据表test1中的数据,结果如下:
![](https://epubservercos.yuewen.com/76103A/15056702904172406/epubprivate/OEBPS/Images/1087.jpg?sign=1739021313-iRclN0hsCMZNKpF6qQG4hMzSMR76Hf1G-0-4f7496e3554ebd68ce4934a5cbddfc45)
从结果可以看出,新插入的0值分配的是4,按照重启前的操作逻辑,此处应该分配6。出现上述结果的主要原因是自增主键没有持久化。
在MySQL 5.7系统中,对于自增主键的分配规则,是由InnoDB数据字典内部一个计数器来决定的,而该计数器只在内存中维护,并不会持久化到磁盘中。当数据库重启时,该计数器会通过下面这种方式初始化。
SELECT MAX(ai_col) FROM table_name FOR UPDATE;
在MySQL 8.0版本中,上述测试步骤最后一步的结果如下:
![](https://epubservercos.yuewen.com/76103A/15056702904172406/epubprivate/OEBPS/Images/1088.jpg?sign=1739021313-8YEglTH4A5893hMACfkAACufT0cQZrrW-0-bd826ccf5856e095b3ce3327a8ed53c4)
从结果可以看出,自增变量已经持久化了。下面讲述MySQL 8.0的解决方案。
MySQL 8.0将自增主键的计数器持久化到重做日志中。每次计数器发生改变,都会将其写入重做日志中。如果数据库重启,InnoDB会根据重做日志中的信息来初始化计数器的内存值。为了尽量减小对系统性能的影响,计数器写入到重做日志时并不会马上刷新数据库系统。