自增变量的持久化 [MySQL][数据库]

自增变量的持久化

在MySQL8.0之前,自增主键AUTO_INCREMENT的值如果大于max(primary key) +1,那么在MySQL重启后,会重置AUTO_INCREMENT = max(primary key)+1,这种现象在某些情况下会导致业务主键冲突或者其他难以发现的一些问题

  • 出现这种问题的原因是因为在MySQL5.7中,对于自增主键的分配规则是由InnoDB数据字典内部一个计数器来决定的,而该计数器维护在了内存中,并不会持久化到磁盘中(也就是硬盘中),当数据库重启的时候,该计数器会被初始化,这个时候初始化的结果就是: auto_increment = max(primary key)+1

而在MySQL8.0中,将自增主键的计数器持久化到了重做日志中,每次计数器发生改变之后,都会将其写入到重做日志中,如果这个时候数据库重启了,那么InnoDB数据字典会根据重做日志中的信息来初始化计数器的内存值

  • 那么使用这种方式,将计数器持久化到重做日志中,然后又将重做日志保存到磁盘中,这个时候即使我们断电(或者说数据库重启之后)我们的重做日志仍然还是会记得我们上一次的自增的值,这个时候就不会出现MySQL5.7中的问题了
下面这里我们通过一个例子来演示自增变量没有持久化之前(也就时MySQL8.0之前)和自增变量持久化之后(也就是MySQL8.0开始到之后)的区别:
  1. 首先我们先来分析在MySQL5.7中的情况
    • 也就是还没有进行自增变量的持久化
CREATE TABLE test9(
id INT PRIMARY KEY AUTO_INCREMENT
);
  • 这里我们先创建一个数据表,这个数据表中设置一个自增列
INSERT INTO test9
VALUES (0),(0),(0),(0);
  • 这个时候我们就是在test9表中添加了4条记录,我们这个时候添加0其实就是默认赋值,因为我们的自增列中是不可以添加0或者null的,那么这个时候表中的四条添加的记录的id字段值就分别为: 1,2,3,4
DELETE FROM test9
WHERE id = 4;
  • 这个时候我们将表中的id为4的字段删除
INSERT INTO test9
VALUES(0);
  • 这个时候我们继续在test9表中添加一条记录,这个时候我们添加的记录的id应该是几? — 这个时候执行之后我们可以发现结果是5, 因为我们前面已经将表中id为4的记录删除了,这个时候下一次自增的时候即使表中没有id为4的字段了,但是这个时候我们也不会添加4,而是添加5 — 其实这个时候就是自增主键的值auto_increment 大于了max(primary key)+1
DELETE FROM test9
WHERE id = 5;
  • 这个时候我们再将表中的id为5的记录删除掉
下面这一步很重要:

这个时候我们要重启数据库

  • 那么我们如何重启数据库?
    1. 我们要在cmd(命令提示符)中用"net stop 数据库"指令来关闭数据库
      • 注意: 这里的数据库不是指定具体的数据库名,而是我们启动的数据库在后台的名字,我们可以去打开的后台中去查询这个名字(通过我的电脑,然后点击右键进入到管理中,然后再管理中找到服务和应用程序,然后点击服务,之后列表里面找我们的数据库的名字就可以了 ( 注意: 前提是我们的数据库已经是启动了 )
    2. 然后在使用"net start 数据库" 指令来启动我们的数据库
INSERT INTO test9
VALUES(0);
  • 然后在重启了数据库之后我们再往这个test9表中去添加一条记录,同样还是添加id 为0,其实也就是默认添加的方式 ---- 那么这个时候添加的id会是6吗?( 按我们之前的想法就应该是6,因为4和5已经被删除了 )

    • 但是这个时候我们执行之后我们可以发现,这里执行的结果中添加的记录的id值为 : 4
    • 这里就是因为我们的数据库重启了之后数据库内存中的数据消失了,这个时候是在MySQL5.7中,这个时候对于自增主键的计数器维护在了内存中,这个时候内存中的数据消失了,那么也就是计数器要重新初始化,这个时候我们计数器初始化就是将自增主键auto_increment 设置为了 max(primary key)+1,也就是将我们自增的值恢复到了表中的最大id+1

但是如果上述的全部操作都执行在MySQL8.0中,这个时候结果就会不相同:

如果是在MySQL8.0中做了同样的操作,那么前面的所有步骤的执行结果都是相同的,但是对于最后一个添加数据的操作(也就是重启了数据库之后的操作),执行的结果就是不同的 ---- 如果是在MySQL8.0中,那么最后一个添加数据的操作之后我们查询表中的数据可以发现我们添加的这条数据的id是6,这个时候为什么是6?

  • 因为在MySQL8.0中我们对于自增列有了持久化的功能,在MySQL8.0中我们添加了一个重做日志,将每次自增列计数器的变化都记录到了重做日志中,并且我们的重做日志被持久化到了磁盘中,所以当我们重启数据库之后我们的重做日志中的数据并不会消失,并且我们重启数据库之后会通过重做日志对自增主键计数器进行初始化,那么这个时候就恢复到了上次关闭数据库前的状态,所以这里添加的这条记录的id就应该为6,因为id为4和5的记录都已经被删除掉了

猜你喜欢

转载自blog.csdn.net/m0_57001006/article/details/123625810