美文网首页
InnoDB引擎对Auto_Increment的处理

InnoDB引擎对Auto_Increment的处理

作者: SawyerLee | 来源:发表于2017-07-17 14:18 被阅读220次

        在一次宕机之后重启Mysql服务器并恢复数据的过程中发现了自增主键列的自增数值会回退,导致有数据上有冲突。经过一番的排查之后发现原来是主键自增值回退了,导致自增主键有重复导致外键关联失效引起的。

    我们来举个例子说明一下具体的现象,例如,创建一个个InNoDB引擎表:

    CREATE TABLE `bsession`  (

    `id` int(10) unsigned NOT NULL AUTO_INCREMENT,

    `aname` varchar(80) NOT NULL DEFAULT ‘’,

    PRIMARY KEY (`id`)

    ) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8;

    创建表测试表

    现在插入10条数据,再删除最后的几条,

    INSERT INTO `bsession` (`aname`) values ('a'),('a'),('a'),('a'),('a'),('a'),('a'),('a'),('a'),('a’);

    DELETE FROM `bsession` where `id` in (8,9,10);

    模拟数据操作

    删除操作之后,表中的数据仅有7条,最大的’id’ = 7。现在进行数据库重启,并重新插入10条数据。此时自增列是从8开始计数,还是从11开始计数呢?我想很多人都认为会从11开始计数,生成新纪录,但实际情况会超出我们的预期,下面我们实际验证一下:

    见证奇迹

    你肯定会问了,这是为什么呢?

    同样我也感觉很奇怪,于是就了解MySql的InnoDB引擎是如何处理自增列的:

    原因是InnoDB引擎对AUTO_INCREMENT计数器是存放到主内存中的,并非硬盘。所以当重启后内存数据就丢失了!

    我们来看官方文档:https://dev.mysql.com/doc/refman/5.7/en/innodb-auto-increment-handling.html,中的【InnoDB AUTO_INCREMENT Counter Initialization】一节的详细说明:

    MySQL官网说明

    不过这个特性将在Mysql的下一个版本8.0中更改,自增计数器每次更改时,当前的最大自增计数器值将会被写入redo log中,并保存到每个检查点的 InnoDB引擎的私有系统表中,实现自增计数器的持久化,重启后会保持一致。

    当服器在Crash中的恢复重启过程中,InnoDB使用存储在系统字典表里的当前最大自增值初始化到内存,并且从最后一个检查点开始扫描Redo Log中写入的计数器值。如果Redo Log中的值大于内存中的计数器值,Redo Log中的值将会被采用。

    关于后续版本中对于 自增列的处理机制 请查看官方文档的详细说明,这里不在赘述。https://dev.mysql.com/doc/refman/8.0/en/innodb-auto-increment-handling.html

    相关文章

      网友评论

          本文标题:InnoDB引擎对Auto_Increment的处理

          本文链接:https://www.haomeiwen.com/subject/uiwfkxtx.html