0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

自增主键去哪了?---一次开发过程中的思考

京东云 ? 来源:jf_75140285 ? 作者:jf_75140285 ? 2024-09-05 14:12 ? 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

前情提要:

最近新接了一个需求,需要去创建两张表,其中有一张表需要根据业务id和业务类型建立唯一索引,对数据唯一性进行约束。

因为涉及到业务嘛,表结构就进行缩略了

表结构示例如下:

CREATE TABLE `example_table` ( 
    `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键', 
    `business_id` bigint(20) unsigned NOT NULL COMMENT '业务ID', 
    `business_type` tinyint(3) unsigned NOT NULL COMMENT '业务类型,', 
    `del` tinyint(1) unsigned DEFAULT '0' COMMENT '删除标识,0表示未删除,1表示删除', 
    `creator` varchar(50) NOT NULL COMMENT '创建人PIN', 
    `modify_date` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', 
    `create_date` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', 
     PRIMARY KEY (`id`), 
     UNIQUE KEY `uk_business_id_and_type` (`business_id`,`business_type`)
 ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COMMENT='示例表'

既然表建立好,那么就是发挥我们编码能力的时候了...此处省略一堆编码时间。

编码结束,自测结束,信心满满的找前端同学进行联调。

因为联调嘛,mock了很多同样的business_id和bussiness_type的数据,结果到了数据库,因为唯一索引的约束,报了一堆错误,插入都失败了。

终于调整了一下mock数据,插入成功了。

但是发生了一个比较神奇的现象

wKgaombZS8uAP3YWAAWjhNZXIGk416.png

主键不是连续自增的了~~ 中间丢失的自增主键去哪了??

关于自增主键

自增主键是我们在设计数据库表结构时经常使用的主键生成策略,主键的生成可以完全依赖数据库,在新增数据的时候,我们只需要将主键设置为null,0或者不设置该字段,数据库就会为我们自动生成一个主键值。

首先,我们要知道 自增主键保存在哪里~

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

1.MyISAM引擎的自增值保存在数据文件中

2.InnoDB引擎的自增值,在MySQL5.7及之前的版本,自增值保存在内存里,并没有持久化。每次重启后,第一次打开表的时候,都会去找自增值的最大值max(id),然后将max(id)+步长(建表语句中的指定步长)作为这个表当前的自增值。在MySQL8.0版本,将自增值的变更记录在了redo log中,重启的时候依靠redo log恢复重启之前的值。

了解了自增主键的保存机制,再了解一下主键这个"自增"逻辑~

wKgaombZS82AQfL8AAIuOmenPaY302.png

插入一条语句分配自增主键id值的流程如图所示。

自增主键不连续的情况

细心的小伙伴一定发现了~咦,这个ID=声明值的话,ID就可以能被随意指定了,那么ID就可能存在不是自增的情况了!

是的,这其实就是第一种自增主键不连续的情况。

第二种不连续的情况就是我们在联调中遇到的问题了

简单来做个测试,目前数据就像一开始的图一样,id自增到了24,下一个插入的应该是25,那么执行一条sql

insert into example_table  values (null,111,1,0,'mock',now(),now());

wKgZombZS8-AJA0AAAD8FU1x49g171.png

插入成功了一条数据,主键是连续自增的。

那么我们模拟一条错误的sql呢(`creator`字段指定错类型)~:

insert into example_table  values (null,112,1,0,mock,now(),now());

果然,执行sql 的时候报出异常:

wKgaombZS9CAOwk1AAEIK9mIHbg535.png

继续执行一条正确的正常的sql,插入结果:

wKgZombZS9GAMw3yAAF4RL7KqZM690.png

主键还是连续自增的。这个发生错误为什么自增主键还是连续的呢。我们模拟一下之前联调遇到的情况,插入一条 sql:

insert into example_table  values (null,112,1,0,'mock',now(),now());

因为id=26的数据buiness_id和bussiness_type 跟新插入的这条数据一样,那么肯定会因为唯一索引插入不成功,果然,执行结果如下:

wKgZombZS9KAUqsUAAFR3CsCMEY955.png

那么,我们修改一下sql继续插入呢?

insert into example_table  values (null,113,1,0,'mock',now(),now())

wKgaombZS9OAAwLcAAG0qbhHNzs175.png

主键发生了"断代",27的主键跑丢了...

明明都是sql插入的时候错误,为什么结果会有差异呢,有的时候主键会丢失,有的时候主键不会丢失呢,想要弄明白这个问题,就需要先明白一下一条sql的执行过程:

wKgZombZS9SAUHeEAAUNZrjqSmE108.png

这里只是针对本文需要关注的点(相信小伙伴对这个执行过程肯定也是非常了解的

审核编辑 黄宇

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 开发
    +关注

    关注

    0

    文章

    373

    浏览量

    41648
  • SQL
    SQL
    +关注

    关注

    1

    文章

    785

    浏览量

    45477
  • 编码
    +关注

    关注

    6

    文章

    972

    浏览量

    55974
收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    使用CY7C65213开发过程中,应该用哪个interface进行uart通信?

    在使用CY7C65213开发过程中,我想用CyUartRead读数据,但是好像没有接口的deviceType是CY_TYPE_UART,想请问我应该用哪个interface进行uart通信? 是否有相关指导文件,或描述符指导?
    发表于 06-03 07:04

    一次消谐装置与二消谐装置区别、一次消谐器与二消谐器的区别

    一次消谐器与二消谐器是电力系统中用于抑制谐振过电压的不同装置,主要区别如下: 安装位置:一次消谐器串联于电压互感器(PT)一次侧中性点与地之间,直接承受高电压;二
    的头像 发表于 05-07 09:58 ?1586次阅读
    <b class='flag-5'>一次</b>消谐装置与二<b class='flag-5'>次</b>消谐装置区别、<b class='flag-5'>一次</b>消谐器与二<b class='flag-5'>次</b>消谐器的区别

    TIM2输入捕获,DMA开启中断传输输入捕获数据,程序跑的过程中,DMA直中断,TIM6只触发一次中断,怎么解决?

    用TIM2捕获输入的数据,并且通过DMA存储,在开启DMA中断同时,TIM6断也开启(用于计时)。但是程序跑的过程中,DMA直中断,TIM6只触发一次中断。
    发表于 03-14 06:39

    欧度MEDI-SNAP一次性医用插头发布

    欧度MEDI-SNAP一次性医用插头产品组加入新成员啦!为满足一次性内窥镜、一次性手术消融刀等设备的耗材需求,欧度将ODU MEDI-SNAP一次
    的头像 发表于 02-21 16:00 ?571次阅读

    在linux下开发过程中, DLP4500 GUI无法连接光机怎么解决?

    在linux下开发过程中, DLP4500 GUI 无法连接光机,出现错误提示如下: open device_handle error: Is a directory opening path
    发表于 02-20 08:41

    如何在日常开发过程中提高代码质量

    。 提高代码质量是个系统工程,本文主要介绍开发人员如何在日常开发过程中提高代码质量。 01 什么是代码质量? 代码质量般用于衡量代码的“好”和“烂”:“好”代码表示代码质量高,“烂
    的头像 发表于 01-23 09:09 ?671次阅读
    如何在日常<b class='flag-5'>开发过程中</b>提高代码质量

    调试ADS1278,读取数据过程中在下一次SYNC低脉冲信号前出现反复进入中断的现象,请问是否正确?

    准备检索变为低,我控制在DRDY下降沿进入中断读取数据(仅读取通道1),但是读取数据过程中在下一次SYNC低脉冲信号前出现反复进入中断的现象,请问是否正确?在时序上还有什么问题吗? 黄色SCLK波形
    发表于 12-25 07:03

    充分考虑设备的体验性易用性 蓝鹏设计部将这理念贯穿于整个研发过程

    设计部还充分考虑设备的易用性。他们深知,个易于使用的设备能够降低用户的学习成本,提高用户的使用效率。因此,在研发过程中,设计部注重从以下几个方面提升设备的易用性: 1.简化操作流程:通过优化设备
    发表于 12-24 14:07

    求助,关于LMK5B12204调试I2C过程中遇到的几个问题求解

    目前在调试I2C过程中遇到如下几个问题: 1)如果HW_SW_CTRL配置成1时(ROM+I2C模式),一次只读取0x0C寄存器的值发现值是0x1b,如果读取两个或者两个以上的寄存器值就发生错误
    发表于 11-13 06:03

    自己做的TAS5825板子软件开发过程中怎么接到PPC3上去调试呢?

    我们打算做个TAS5825的板子,PPC3软件已经申请下来了,有个问题是我们自己做的TAS5825板子软件开发过程中怎么接到PPC3上去调试呢?
    发表于 10-15 08:15

    一次电源与二电源有什么不同

    在电力系统和电子设备的供电领域中,一次电源与二电源是两个至关重要的概念。它们各自承担着不同的功能和角色,共同确保电力供应的稳定性和可靠性。本文将对一次电源与二电源的定义、区别以及它
    的头像 发表于 10-10 14:10 ?5649次阅读

    一次电池分类以及应用场景详解

    01 一次电池简介 一次电池即原电池(primarycell、primarybattery)(俗称干电池),是放电后不能再充电使其复原的电池,通电电池有正极、负极电解以及容器和隔膜等组成。 一次电池
    的头像 发表于 09-30 17:52 ?3024次阅读
    <b class='flag-5'>一次</b>电池分类以及应用场景详解

    ODU MEDI-SNAP一次性医用插拔锁插头产品介绍

    为满足一次性内窥镜、一次性手术消融刀等设备的耗材需求,欧度全新推出了MEDI-SNAP一次性医用插拔锁插头,为医疗客户打造
    的头像 发表于 09-10 09:59 ?923次阅读

    康谋分享 | 在基于场景的AD/ADAS验证过程中,识别挑战性场景!

    基于场景的验证是AD/ADAS系统开发过程中的重要步骤,然而面对海量驾驶记录数据时,如何实现自动且高效地识别、分类和提取驾驶记录的挑战性场景?本文康谋为您介绍IVEX软件识别挑战性场景并进行数据分析的强大功能。
    的头像 发表于 08-28 10:16 ?1497次阅读
    康谋分享 | 在基于场景的AD/ADAS验证<b class='flag-5'>过程中</b>,识别挑战性场景!

    电气一次设备有哪些其功能是什么

    电气一次设备是指那些直接参与电能的生产、转换以及输配过程的设备。这些设备在电力系统扮演着核心角色,确保电能从生产到消费的各个环节能够高效、安全地进行。具体来说,电气一次设备主要包括以
    的头像 发表于 08-27 14:50 ?2498次阅读