当前位置:首页 >综合 >MySQL小知识点:自增主键为什么不是连续的?自增id用完怎么办? 点自的自我们创建一个表t

MySQL小知识点:自增主键为什么不是连续的?自增id用完怎么办? 点自的自我们创建一个表t

2024-06-30 16:42:53 [百科] 来源:避面尹邢网

MySQL小知识点:自增主键为什么不是知识增主增连续的?自增id用完怎么办?

作者:做好一个程序猿 数据库 MySQL 今天我们就来说说这个问题,看看什么情况下自增主键会出现 “空洞”?为了便于说明,点自的自我们创建一个表t,连续其中id是完办自增主键字段、c是知识增主增唯一索引。

自增主键为什么不是点自的自连续的

今天我们就来说说这个问题,看看什么情况下自增主键会出现 “空洞”?连续

为了便于说明,我们创建一个表t,完办其中id是知识增主增自增主键字段、c是点自的自唯一索引。

MySQL小知识点:自增主键为什么不是连续的?自增id用完怎么办? 点自的自我们创建一个表t

CREATE TABLE `t` (`id` int(11) NOTNULLAUTO_INCREMENT,连续`c` int(11) DEFAULTNULL,`d` int(11) DEFAULTNULL,PRIMARY KEY (`id`),UNIQUE KEY `c` (`c`)) ENGINE=InnoDB;

自增值保存在哪儿?

在这个空表t里面执行insert into t values(null, 1, 1);插入一行数据,再执行show create table命令,完办就可以看到如下图所示的知识增主增结果:

MySQL小知识点:自增主键为什么不是连续的?自增id用完怎么办? 点自的自我们创建一个表t

图1 自动生成的AUTO_INCREMENT值图1 自动生成的AUTO_INCREMENT值

MySQL小知识点:自增主键为什么不是连续的?自增id用完怎么办? 点自的自我们创建一个表t

可以看到,表定义里面出现了一个AUTO_INCREMENT=2,点自的自表示下一次插入数据时,连续如果需要自动生成自增值,会生成id=2。

其实,这个输出结果容易引起这样的误解:自增值是保存在表结构定义里的。实际上,表的结构定义存放在后缀名为.frm的文件中,但是并不会保存自增值。

不同的引擎对于自增值的保存策略不同。

  • MyISAM引擎的自增值保存在数据文件中。
  • InnoDB引擎的自增值,其实是保存在了内存里,并且到了MySQL 8.0版本后,才有了“自增值持久化”的能力,也就是才实现了“如果发生重启,表的自增值可以恢复为MySQL重启前的值”,具体情况是:在MySQL 5.7及之前的版本,自增值保存在内存里,并没有持久化。每次重启后,第一次打开表的时候,都会去找自增值的最大值max(id),然后将max(id)+1作为这个表当前的自增值。

举例来说,如果一个表当前数据行里最大的id是10,AUTO_INCREMENT=11。这时候,我们删除id=10的行,AUTO_INCREMENT还是11。但如果马上重启实例,重启后这个表的AUTO_INCREMENT就会变成10。

也就是说,MySQL重启可能会修改一个表的AUTO_INCREMENT的值。

在MySQL 8.0版本,将自增值的变更记录在了redo log中,重启的时候依靠redo log恢复 重启之前的值。 理解了MySQL对自增值的保存策略以后,我们再看看自增值修改机制。

自增值修改机制

在MySQL里面,如果字段id被定义为AUTO_INCREMENT,在插入一行数据的时候,自增值的行为如下:

1. 如果插入数据时id字段指定为0、null 或未指定值,那么就把这个表当前的AUTO_INCREMENT值填到自增字段;

2. 如果插入数据时id字段指定了具体的值,就直接使用语句里指定的值。根据要插入的值和当前自增值的大小关系,自增值的变更结果也会有所不同。假设,某次要插入的值是X,当前的自增值是Y。

1. 如果X

2. 如果X≥Y,就需要把当前自增值修改为新的自增值。

自增值的修改时机

假设,表t里面已经有了(1,1,1)这条记录,这时我再执行一条插入数据命令:

insert into t values(null, 1, 1);

这个语句的执行流程就是:

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

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

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

4. 将表的自增值改成3;

5. 继续执行插入数据操作,由于已经存在c=1的记录,所以报Duplicate keyerror,语句返回。

对应的执行流程图如下:

图2 insert(null, 1,1)唯一键冲突图2 insert(null, 1,1)唯一键冲突

可以看到,这个表的自增值改成3,是在真正执行插入数据的操作之前。这个语句真正执行的时候,因为碰到唯一键c冲突,所以id=2这一行并没有插入成功,但也没有将自增值再改回去。所以,在这之后,

唯一键冲突是导致自增主键id不连续的第一种原因。同样地,事务回滚也会产生类似的现象,这就是第二种原因。

自增id用完怎么办?

MySQL里有很多自增的id,每个自增id都是定义了初始值,然后不停地往上加步长。虽然自然数是没有上限的,但是在计算机里,只要定义了表示这个数的字节长度,那它就有上限。比如,无符号整型(unsigned int)是4个字节,上限就是232 -1。

既然自增id有上限,就有可能被用完。但是,自增id用完了会怎么样呢?

表定义自增值id

表定义的自增值达到上限后的逻辑是:再申请下一个id时,得到的值保持不变。 我们可以通过下面这个语句序列验证一下:

create table t(id int unsigned auto_increment primary key) auto_increment=4294967295;insert into t values(null);//成功插入一行 4294967295show create table t;/* CREATE TABLE `t` (`id` int(10) unsigned NOTNULLAUTO_INCREMENT,PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=4294967295;*/insert into t values(null);//Duplicate entry '4294967295' for key 'PRIMARY'

可以看到,第一个insert语句插入数据成功后,这个表的AUTO_INCREMENT没有改变(还是4294967295),就导致了第二个insert语句又拿到相同的自增id值,再试图执行插入语句,报主

键冲突错误。

4294967295不是一个特别大的数,对于一个频繁插入删除数据的表来说,是可能会被用完的。因此在建表的时候你需要考察你的表是否有可能达到这个上限,如果有可能,就应该创 建成8个字节的bigint unsigned。

InnoDB系统自增row_id

如果你创建的InnoDB表没有指定主键,那么InnoDB会给你创建一个不可见的,长度为6个字节的row_id。InnoDB维护了一个全局的dict_sys.row_id值,所有无主键的InnoDB表,每插入一行数据,都将当前的dict_sys.row_id值作为要插入数据的row_id,然后把dict_sys.row_id的值加1。

实际上,在代码实现时row_id是一个长度为8字节的无符号长整型(bigint unsigned)。但是,InnoDB在设计时,给row_id留的只是6个字节的长度,这样写到数据表中时只放了最后6个字节,所以row_id能写到数据表中的值,就有两个特征:

1. row_id写入表中的值范围,是从0到248 -1;

2. 当dict_sys.row_id=248 时,如果再有插入数据的行为要来申请row_id,拿到以后再取最后6个

字节的话就是0。

也就是说,写入表的row_id是从0开始到248 -1。达到上限后,下一个值就是0,然后继续循环。当然,这个值本身已经很大了,但是如果一个MySQL实例跑得足够久的话,还是可能达到这个上限的。在InnoDB逻辑里,申请到row_id=N后,就将这行数据写入表中;如果表中已经存在row_id=N的行,新写入的行就会覆盖原有的行。

责任编辑:华轩 来源: 今日头条 Mysql自增主键

(责任编辑:时尚)

    推荐文章
    • 什么叫卖出平仓?强制平仓是什么意思

      什么叫卖出平仓?强制平仓是什么意思平仓,是指期货交易者买入或者卖出与其所持股指期货的品种、数量及交割月份相同但交易方向相反的股指期货合约,了结股指期货交易的行为。简单的说就是将手里面的股票抛售出去,但是不一定能马上卖得掉,要有人接你的 ...[详细]
    • ​映泰推出H610MHC

      ​映泰推出H610MHC​映泰现已推出了全新H610MHC-E主板,定位入门级别。映泰现已推出了全新H610MHC-E主板。H610MHC-E主板定位入门级别,无论是办公还是日常影音娱乐都可以很好的满足。H610MHC-E基 ...[详细]
    • 内存频率怎样计算?我来教会你

      内存频率怎样计算?我来教会你内存频率怎样计算?我来教会你作者:霍杰华 2019-07-04 15:57:16商务办公 我们都知道内存有频率,现阶段我们使用的DDR4内存频率一般都是2133MHz、2400MHz、2600MHz. ...[详细]
    • Unity首席执行官被扒“黑历史” 曾试图在FPS游戏中让玩家按子弹付费

      Unity首席执行官被扒“黑历史” 曾试图在FPS游戏中让玩家按子弹付费游戏引擎Unity近日因改变其定价模式,试图按游戏下载量向游戏开发商收取费用而引起巨大争议,Unity多年来一直是独立游戏开发者的首选引擎,这一策略让独立游戏开发者感到恐惧和困惑,不少开发者已经在考虑 ...[详细]
    • 苏宁易购(002024)融资融券余额35.34亿元(03

      苏宁易购(002024)融资融券余额35.34亿元(03苏宁易购(002024)2021年3月23日融资融券信息显示,苏宁易购融资余额3,515,840,678元,融券余额18,514,178元,融资买入额16,294,686元,融资偿还额11,938,9 ...[详细]
    • 数据加密的好处:保护智能建筑!

      数据加密的好处:保护智能建筑!数据加密的好处:保护智能建筑!2022-10-10 11:08:09安全 数据安全 通过了解数据加密的好处,可以创建一个强大的安全解决方案,以确保自身的资产安全。 企业越来越多地采用智能建筑来提高能源 ...[详细]
    • 深入浅出 Zookeeper 中的 ZAB 协议

      深入浅出 Zookeeper 中的 ZAB 协议深入浅出 Zookeeper 中的 ZAB 协议作者:悟空聊架构 2022-03-23 18:58:11网络 无线技术 本篇尽量用大白话+画图的方式进行讲解Zookeeper 中的 ZAB 协议,希望 ...[详细]
    • 物联网如何改变中小企业的经营方式

      物联网如何改变中小企业的经营方式物联网如何改变中小企业的经营方式作者:Harris编译 2022-06-09 10:44:08物联网 商业物联网(IoT)是一种强大的创新技术,使企业的业务能够向前发展、扩展现有机会并发现新机会、保持 ...[详细]
    • 中国石化一季度全力优化生产经营 业绩取得高质量开门红

      中国石化一季度全力优化生产经营 业绩取得高质量开门红4月27日,中国石化发布2022年一季度业绩报告。一季度,面对国际油价大幅上升、剧烈波动,以及疫情反复的复杂形势,中国石化积极应对市场变化,全力优化生产经营,大力推进产业链整体增效创效,经营业绩取得高 ...[详细]
    • 「外社堂」魔兽重制版要来了 快准备一套高配外设吧

      「外社堂」魔兽重制版要来了 快准备一套高配外设吧有生之年的《魔兽争霸III:重制版》将在2019年上市,喜欢魔兽的小伙伴们一定在搓手期待了吧。如果想要畅快地玩RTS游戏,除了需要过人的意识,飞快的手速外,还需要一套好用的外设装备,这里有几款高端向的 ...[详细]
    热点阅读