图1

图1中是表t原有的数据,这个时候我们执行show create table t会看到如下输出,如图二所示现在的自增值是2,也就是下一个不指定主键值的插入的数据的主键就是2

图2

Innodb引擎的自增值,是保存在内存中的,并且到了mysql8.0版本后,才有了“自增值持久化”的能力,也就是才实现了"如果发生重启,表的自增值可以恢复为mysql重启前的值"

也就说在mysql5.7及之前的版本,自增值保存在内存中,并没有持久化,每次重启后,第一次打开表的时候,都会去找自增值的最大值max(id),然后讲max(id)+1作为当前表的自增值

举例来说,如果一个表中当前数据行的最大id=3,自增值=4,这个时候我们删除id=3的数据后,自增值还是=4,但是这个时候如果马上重启,重启后这个表的自增值就会变成3,

我们可以做个实验:

这个时候的自增值=4

我们删掉了id=3的数据

然后我们在查询一下自增值,我们可以看到这个时候的自增值还是4

然后我们在重启以后在查询一下,可以看到这个时候的自增值就是3了

在mysql8.0版本,将自增值的变更记录在了redo log中,重启的时候依靠redo log恢复重启之前的值

接下来我们在做个实验说明一下自增值为啥不是连续的,我们刚才建的表t的c字段我加了唯一索引,现在我们表中的自增值应该是3对吧,因为刚才我重启过了,然后我们执行INSERT INTO t VALUES(NULL,2,3)

这条语句,会报错插入失败,这条语句的执行流程是这样的

1,执行器调用innodb引擎接口写入一行,传入的这一行的值是(0,2,3);

2,innodb发现用户没有指定自增id的值,获取表t当前的自增值3;

3,将传入的行的值改成(3,1,1);

4,将表的自增值改成4;

5,继续执行插入数据操作,由于已经存在C=2的记录,所以报Duplicate key eror,语句返回

然后我们在查询一下自增值,看到了没有,现在的自增值已经变成了4,也就说上面这条语句插入失败以后,自增值没有回滚,这样下次我们在插入数据的时候的主键值就是4,就会造成我们的主键值不一致

所以说,唯一键冲突是导致自增主键id不连续的第一种原因

同样的,事务回滚也会产生类似的现象,这就是第二种原因

你可能会问,为什么在出现唯一键冲突或者事务回滚的时候,mysql没有把表t的自增值改回去呢?如果把表t的当前自增值从4改回3,再插入新数据的时候,不就可以生成id=3的一行数据了吗?

其实,mysql这么设计是为了提升性能,接下来,分析一下这个设计思路,看看自增值为什么不能回退

假设有两个并行执行的事务,在申请自增值的时候,为了避免两个事务申请到相同的自增id,肯定要加锁,然后顺序申请

1.假设事务A申请到了id=2,事务B申请到id=3,那么这时候表t的自增值是4,之后继续执行

2.事务B正确提交了,但事务A出现了唯一键冲突

3.如果允许事务A把自增id回退,也就是把表t的当前自增值改成2,那么就会出现这样的情况:表里面已经有id=3的行,而当前的自增id值是2

4.接下来,继续执行的其他事务就会申请到id=2,然后在申请到id=3,这时候,就会出现插入语句报错“主键冲突"

而为了解决这个主键冲突,有两种方法:

1,每次申请id之前,先判断表里面是否已经存在这个id,如果存在,就跳过这个id,但是,这个方法的成本很高,因为,本来申请id是一个很快的操作,现在还要再去主键索引树上判断id是否存在

2,把自增id的锁范围扩大,必须等到一个事务执行完成并提交,下一个事务才能再申请自增id,这个方法的问题,就是锁的粒度太大,系统并发能力大大下降

可见,这两个方法都会导致性能问题,造成这些麻烦的罪魁祸首,就是我们假设的这个”允许自增id回退“的前提导致的,

因此,innodb放弃了这个设计,语句执行失败也不回退自增id,也正是因为这样,所有才只保证了自增id是递增的,但不保证是连续的。

mysql的innodb自增主键为什么不是连续的的更多相关文章

  1. java面试一日一题:mysql中的自增主键

    问题:请讲下mysql中的自增主键 分析:该问题主要考察对mysql中自增主键的掌握,使用场景及如何设置 回答要点: 主要从以下几点去考虑 1.什么自增主键 2.使用场景是什么: 3.innodb_a ...

  2. INNODB自增主键的一些问题 vs mysql获得自增字段下一个值

    今天发现 批量插入下,自增主键不连续了....... InnoDB AUTO_INCREMENT Lock Modes This section describes the behavior of A ...

  3. INNODB自增主键的一些问题

    背景: 自增长是一个很常见的数据属性,在MySQL中大家都很愿意让自增长属性的字段当一个主键.特别是InnoDB,因为InnoDB的聚集索引的特性,使用自增长属性的字段当主键性能更好,这里要说明下自增 ...

  4. mycat分布式mysql中间件(自增主键)

    一.全局序列号 全局序列号是MyCAT提供的一个新功能,为了实现分库分表情况下,表的主键是全局唯一,而默认的MySQL的自增长主键无法满足这个要求.全局序列号的语法符合标准SQL规范,其格式为:nex ...

  5. 《Mysql - 自增主键为何不是连续的?》

    一:自增主键是连续的么? - 自增主键不能保证连续递增. 二:自增值保存在哪里? - 当使用 show create table `table_name`:时,会看到 自增值,也就是 AUTO_INC ...

  6. Innodb自增主键与sql_mode

    1.自增主键 1.设置自增主键 建表设置自增主键,设置自增主键需要唯一约束,否则会报错.(即指定列数据唯一) mysql> create table test_zz(id int auto_in ...

  7. MySQL 中的自增主键

    MySQL 的主键可以是自增的,那么如果在断电重启后新增的值还会延续断电前的自增值吗?自增值默认为1,那么可不可以改变呢?下面就说一下 MySQL 的自增值. 特点 保存策略 1.如果存储引擎是 My ...

  8. mysql 自增主键为什么不是连续的?

    由于自增主键可以让主键索引尽量地保持递增顺序插入,避免了页分裂,因此索引更紧凑 MyISAM 引擎的自增值保存在数据文件中 nnoDB 引擎的自增值,其实是保存在了内存里,并且到了 MySQL 8.0 ...

  9. MySQL 插入与自增主键值相等的字段 与 高并发下保证数据准确的实验

    场景描述: 表t2 中 有 自增主键 id  和 字段v  当插入记录的时候 要求 v与id 的值相等(按理来说这样的字段是需要拆表的,但是业务场景是 只有某些行相等 ) 在网上搜的一种办法是 先获取 ...

随机推荐

  1. 当我们谈 SQL 优化时在谈些什么?

    作者 |孙银行编辑 | 顾乡 背景 Mysql数据库作为数据持久化的存储系统,在实际业务中应用广泛.在应用也经常会因为SQL遇到各种各样的瓶颈.最常用的Mysql引擎是innodb,索引类型是B-Tr ...

  2. 并发模型(二)——Master-Worker模式

    Master-Worker模式是常用的并行模式之一,它的核心思想是,系统有两个进程协作工作:Master进程,负责接收和分配任务:Worker进程,负责处理子任务.当Worker进程将子任务处理完成后 ...

  3. SQL Server Database Backup and Restore in C#

    SQL Server Database Backup and Restore in C# Syed Noman Ali Shah,                          7 Feb 201 ...

  4. [原创]Spring boot 框架构建jsp web应用

    说明 Spring boot支持将web项目打包成一个可执行的jar包,内嵌tomcat服务器,独立部署 为支持jsp,则必须将项目打包为war包 pom.xml中设置打包方式 <packagi ...

  5. 异常:java.lang.IllegalStateException: Ambiguous handler methods mapped for HTTP path '/app/userInfoMaint/getProvince.do'

    调试代码时出现异常:java.lang.IllegalStateException: Ambiguous handler methods mapped for HTTP path '/app/user ...

  6. python实现文件下载的方法总结

    前端时间遇到一个通过url下载文件的需求,只需要简单的编写一个py脚本即可.从网上搜了下python实现文件下载的方法,总结如下,备查. 以下方法均已测试,环境win8.1  python2.6/2. ...

  7. 嵌入式Linux启动配置文件及脚本分…

    使用Busybox制作根文件系统时,/etc目录非常重要,它包含了嵌入式Linux启动所需的配置文件及脚本.由于init进程,或者说linuxrc程序会解析inittab文件,因此就从/etc/ini ...

  8. 分布式文件系统MFS(moosefs)实现存储共享

    分布式文件系统MFS(moosefs)实现存储共享(第二版) 作者:田逸(sery@163.com) 由于用户数量的不断攀升,我对访问量大的应用实现了可扩展.高可靠的集群部署(即lvs+keepali ...

  9. Tensorflow训练结果测试

    代码参考(https://blog.csdn.net/disiwei1012/article/details/79928679) import osimport sysimport randomimp ...

  10. 安装CentOS 6网络配置问题

    安装CentOS 6网络配置问题 今天决定把家中的CentOS从5升级至6.但安装完CentOS 6.2之后发现eth0没有像往常一样通过DHCP自动获取IP.打开“/etc/sysconfig/ne ...