面试官:MySQL自增主键一定是连续的吗?
测试环境:
MySQL版本:8.0
数据库表:T (主键id,唯一索引c,普通字段d)
如果你的业务设计依赖于自增主键的连续性,这个设计假设自增主键是连续的。但实际上,这样的假设是错的,因为自增主键不能保证连续递增。
一、自增值的属性特征:
1. 自增主键值是存储在哪的?
MySQL5.7版本
在 MySQL 5.7 及之前的版本,自增值保存在内存里,并没有持久化。每次重启后,第一次打开表的时候,都会去找自增值的最大值 max(id)
,然后将 max(id)+1
作为这个表当前的自增值。
MySQL8.0之后版本
在 MySQL 8.0 版本,将自增值的变更记录在了 redo log
中,重启的时候依靠 redo log
恢复重启之前的值。
可以通过看表详情查看当前自增值,以及查看表参数详情AUTO_INCREMENT
值(AUTO_INCREMENT
就是当前数据表的自增值)
2. 自增主键值的修改机制?
在表t中,我定义了主键id为自增值,在插入一行数据的时候,自增值的行为如下:
-
如果插入数据时 id 字段指定为 0、null 或未指定值,那么就把这个表当前的
AUTO_INCREMENT
值填到自增字段; -
如果插入数据时 id 字段指定了具体的值,就直接使用语句里指定的值。
根据要插入的值和当前自增值的大小关系,自增值的变更结果也会有所不同。假设,某次要插入的值是 X,当前的自增值是 Y。
-
如果 X<Y,那么这个表的自增值不变;
-
如果 X≥Y,就需要把当前自增值修改为新的自增值。
二、新增语句自增主键是如何变化的:
我们执行以下SQL语句,来观察自增主键是如何进行变化的
insert into t values(null, 1, 1);
流程图如下所示
流程步骤:
-
AUTO_INCREMENT=1 (表示下一次插入数据时,如果需要自动生成自增值,会生成 id=1。)
-
insert into t values(null, 1, 1) (执行器调用 InnoDB 引擎接口写入一行,传入的这一行的值是 (0,1,1))
-
get AUTO_INCREMENT=1 (InnoDB 发现用户没有指定自增 id 的值,获取表 t 当前的自增值 1 )
-
AUTO_INCREMENT=2 insert into t values(1, 1, 1) (将传入的行的值改成 (1,1,1),并把自增值改为2)
-
insert (1,1,1) 执行插入操作,至此流程结束
大家可以发现,在这个流程当中是先进行自增值的+1,在进行新增语句的执行的。大家可以发现这个操作并没有进行原子操作,如果SQL语句执行失败,那么自增是不是就不会连续了呢?
三、自增主键值不连续情况:(唯一主键冲突)
当我执行以下SQL语句时
insert into t values(null, 1, 1);
第一次我们可以进行新增成功,根据自增值的修改机制。如果插入数据时 id 字段指定为 0、null 或未指定值,那么就把这个表当前的 AUTO_INCREMENT
值填到自增字段;
当我们第二次在执行以下SQL语句时,就会出现错误。因为我们表中c字段是唯一索引,会出现Duplicate key error
错误导致新增失败。
例如:
-
AUTO_INCREMENT=2 (表示下一次插入数据时,如果需要自动生成自增值,会生成 id=2。)
-
insert into t values(null, 1, 1) (执行器调用 InnoDB 引擎接口写入一行,传入的这一行的值是 (0,1,1))
-
get AUTO_INCREMENT=2 (InnoDB 发现用户没有指定自增 id 的值,获取表 t 当前的自增值 2 )
-
AUTO_INCREMENT=3 insert into t values(2, 1, 1) (将传入的行的值改成 (2,1,1),并把自增值改为3)
-
insert (2,1,1) 执行插入操作,由于已经存在 c=1 的记录,所以报
Duplicate key error
,语句返回。
可以看到,这个表的自增值改成 3,是在真正执行插入数据的操作之前。这个语句真正执行的时候,因为碰到唯一键 c 冲突,所以 id=2 这一行并没有插入成功,但也没有将自增值再改回去。所以,在这之后,再插入新的数据行时,拿到的自增 id 就是 3。也就是说,出现了自增主键不连续的情况。
四、自增主键值不连续情况:(事务回滚)
其实事务回滚原理也和上面一样,都是因为异常导致新增失败,但是自增值没有进行回退。
五、自增主键值不连续情况:(批量插入)
批量插入数据的语句,MySQL 有一个批量申请自增 id 的策略:
-
语句执行过程中,第一次申请自增 id,会分配 1 个;
-
1 个用完以后,这个语句第二次申请自增 id,会分配 2 个;
-
2 个用完以后,还是这个语句, 第三次申请自增 id,会分配 4 个;
-
依此类推,同一个语句去申请自增 id,每次申请到的自增 id 个数都是上一次的两倍。
执行以下SQL语句(在表t中先新增了4条数据,在创建表tt把表t数据进行批量新增)
insert into t values(null, 1,1);
insert into t values(null, 2,2);
insert into t values(null, 3,3);
insert into t values(null, 4,4);
create table tt like t;
insert into tt(c,d) select c,d from t;insert into tt values(null, 5,5);
第一次申请到了 id=1,第二次被分配了 id=2 和 id=3, 第三次被分配到 id=4 到 id=7。当我们再执行 insert into t2 values(null, 5,5)
,实际上插入的数据就是(8,5,5),出现了自增主键不连续的情况。
六、自增主键值的优化
1.什么是自增锁
自增锁是一种比拟非凡的表级锁。并且在事务向蕴含了 AUTO_INCREMENT
列的表中新增数据时就会去持有自增锁,假如事务 A 正在做这个操作,如果另一个事务 B 尝试执行 INSERT语句,事务 B 会被阻塞住,直到事务 A 开释自增锁。
2.自增锁有哪些优化
在 MySQL 5.0 版本的时候,自增锁的范围是语句级别。也就是说,如果一个语句申请了一个表自增锁,这个锁会等语句执行结束以后才释放。显然,这样设计会影响并发度。在MySQL 5.1.22 版本引入了一个新策略,新增参数 innodb_autoinc_lock_mode
,默认值是 1。
传统模式(Traditional)
这个参数的值被设置为 0 时,表示采用之前 MySQL 5.0 版本的策略,即语句执行结束后才释放锁;
传统模式他可以保证数据一致性,但是如果有多个事务并发的执行 INSERT 操作,AUTO-INC
的存在会使得 MySQL 的性能略有降落,因为同时只能执行一条 INSERT 语句。
间断模式(Consecutive)
这个参数的值被设置为 1 时:普通 insert 语句,自增锁在申请之后就马上释放;类似 insert … select
这样的批量插入数据的语句,自增锁还是要等语句结束后才被释放;
间断模式他可以保证数据一致性,但是如果有多个事务并发的执行 INSERT 批量操作时,就会进行锁等待状态。如果我们业务插入数据量很大时,这个时候MySQL的性能就会大大下降。
穿插模式(Interleaved)
这个参数的值被设置为 2 时,所有的申请自增主键的动作都是申请后就释放锁。
穿插模式他没有进行任何的上锁设置。在一定情况下是保证了MySQL的性能,但是他无法保证数据的一致性。如果我们在穿插模式下进行主从复制时,如果你的binlog格式不是row格式,主从复制就会出现不一致。
七、MySQL8.0做了哪些优化
在MySQL8.0之后版本,已经默认设置为 innodb_autoinc_lock_mode=2
, binlog_format=row.
。这样更有利与我们在 insert … select
这种批量插入数据的场景时,既能提升并发性,又不会出现数据一致性问题。
相关文章:

面试官:MySQL自增主键一定是连续的吗?
测试环境: MySQL版本:8.0 数据库表:T (主键id,唯一索引c,普通字段d) 如果你的业务设计依赖于自增主键的连续性,这个设计假设自增主键是连续的。但实际上,这样的假设是错的…...

2023ACP世界大赛教育者论坛:让职业教育直面AI机遇与挑战
“AI技术的普及对创意行业和教育带来的影响和变革-2023 Adobe Certified Professional教育者论坛”在苏州西交利物浦大学成功举办。 本次论坛,由Adobe Certified Professional 世界大赛中国赛区组委会主办,联动了来自院校、海内外杰出的创意公司及国际知…...

Unity基础 音频组件以及音频播放
在游戏开发中,声音是一个重要的环节。Unity中的声音组件可以帮助开发者轻松地控制游戏中音频的播放、音量、循环等属性,从而实现更好的游戏体验。本文将详细介绍Unity声音组件的相关概念和技术,以及其在游戏、影视等领域的广泛应用和发展前景…...

SAP-MM-采购申请审批那些事!
1、ME55不能审批删除行项目的PR 采购申请审批可以设置行项目审批或抬头审批。如果设置为抬头审批时,ME55集中审批时,就会发现有些采购申请时不能审批的, 那么这些采购申请时真的不需要审批么?不是的,经过核对这些采购申…...

专业解读财务共享实现财务数智化转型的有效路径
近年来,随着数字经济的飞速发展,各大企业全面开启数智化转型之路,作为企业数智化转型的重要内容,财务数智化转型始于财务共享服务。然而,财务共享建设并不是一蹴而就的,如何通过财务共享实现财务数智化转型…...

九章云极DataCanvas公司诚邀您共享AI基础软件前沿技术盛宴
“杭州通用人工智能论坛暨AIIA人工智能产业发展大会”将于2023年5月30日-31日在杭州举办。本次人工智能产业发展大会由中国信息通信研究院、中国人工智能产业发展联盟主办,杭州城西科创大走廊管委会、杭州市经济和信息化局、杭州未来科技城管理委员会、人工智能关键…...

【高级语言程序设计(一)】第 10 章:文件
目录 一、文件概述 (1)文件定义 (2)文件命名 (3)文件分类 ① 按照文件的内容划分 ② 按照文件的组织形式划分 ③ 按照文件的存储形式划分 ④ 按照文件的存储介质划分 (4)文…...
Android 宿主启动插件中的Activity和Service
在宿主App中加载插件App中的四大组件,需要以下几个步骤: 1. 预先在宿主的AndroidManifest文件中声明插件中的四大组件 <?xml version"1.0" encoding"utf-8"?> <manifest xmlns:android"http://schemas.android.co…...

00后卷王自述,我真的很卷吗?
前段时间我去面试了一个软件测试公司,成功拿到了offer,薪资也从10k涨到了18k,对于工作都还没两年的我来说,还是比较满意的,毕竟有些工作了3到4年的可能还没有我的高。 在公司一段时间后大家都说我是卷王,其…...

真题详解(树的结点)-软件设计(八十四)
真题详解(汇总)-软件设计(八十三)https://blog.csdn.net/ke1ying/article/details/130856130?spm1001.2014.3001.5501 COCOMOII估算不包括_____。 对象点 B.功能点 C.用例数 D.源代码行 答案:C 语法翻译是一种ÿ…...

LDA算法实现鸢尾花数据集降维
目录 1. 作者介绍2. LDA降维算法2.1 基本概念2.2 算法流程 3. LDA算法实现3.1 数据集介绍3.2 代码实现3.3 结果展示 1. 作者介绍 唐杰,男,西安工程大学电子信息学院,2022级研究生 研究方向:机器视觉与人工智能 电子邮件ÿ…...

深入理解Linux虚拟内存管理
系列文章目录 Linux 内核设计与实现 深入理解 Linux 内核(一) 深入理解 Linux 内核(二) Linux 设备驱动程序(一) Linux 设备驱动程序(二) Linux 设备驱动程序(三…...

自动化测试框架、Python面向对象以及POM设计模型简介
目录 1 自动化测试框架概述 2 自动化测试框架需要的环境 3 自动化测试框架设计思想:Python面向对象 4 自动化测试框架设计思想:POM(Page Object Model)页面对象模型 1 自动化测试框架概述 所谓的框架其实就是一个解决问题…...

【CSSpart4--盒子模型】
CSSpart4--盒子模型 网页布局的三大核心:盒子模型,浮动,定位网页布局的过程(本质):盒子模型的组成四部分:边框,内容,内边距,外边距 一 、盒子边框border:1.1 …...

Linux - Java 8 入门安装与重装教程集锦
一、入门初始安装 1. 具体安装教程 1. linux 系统中如何安装java环境(通过tar.gz文件) 安装包下载链接 Java 的 tar.gz 安装包下载链接传送门 Linux 系统的 Java 环境变量配置教程 1. linux查看java版本,以及配置java home 2. Linux环…...

2023年最新企业网盘排行榜出炉
随着云计算技术的不断发展,企业日常工作中大量的资料、文档等信息需要实现集中管理,此时企业网盘工具就应运而生。企业网盘是一种可用于企业内部管理、团队协作及文件共享的云存储平台,能够极大提高企业办公效率和安全性。 一、企业网盘的帮助…...
C++内存分类
内存分配方式(内存布局): 内存5分类 堆、栈、自由存储区、全局/静态存储区、常量存储区 (1)栈:内存由编译器在需要时自动分配和释放。通常用来存储局部变量和函数参数,函数调用后返回的地址。(为运行函数而…...

不是说00后已经躺平了吗,怎么还是这么卷.....
都说00后已经躺平了,但是有一说一,该卷的还是卷。 前段时间我们部门就来了个00后,工作都还没两年,跳到我们公司起薪20K,都快接近我了。 后来才知道人家是个卷王,从早干到晚就差搬张床到工位睡觉了。最近和…...

国内免费版ChatGPT
目录 前言:网站大全 1. ChatGPT是什么 2. ChatGPT的发展历程 3. ChatGPT对程序员的影响 4. ChatGPT对普通人的影响 5. ChatGPT的不足之处 前言:网站大全 AI文本工具站 (laicj.cn) ——gpt-3.5 功能强大(推荐) Chatgpt在线网页版-…...

常用本地事务和分布式事务解决方案模型
目录 1 DTP模型2 2PC2.1 方案简介2.2 处理流程2.2.1 阶段1:准备阶段2.2.2 阶段2:提交阶段 2.3 方案总结 3 3PC3.1 方案简介3.2 处理流程3.2.1 阶段1:canCommit3.2.2 阶段2:preCommit3.3.3 阶段3:do Commit 3.3 方案总结…...
模型参数、模型存储精度、参数与显存
模型参数量衡量单位 M:百万(Million) B:十亿(Billion) 1 B 1000 M 1B 1000M 1B1000M 参数存储精度 模型参数是固定的,但是一个参数所表示多少字节不一定,需要看这个参数以什么…...

练习(含atoi的模拟实现,自定义类型等练习)
一、结构体大小的计算及位段 (结构体大小计算及位段 详解请看:自定义类型:结构体进阶-CSDN博客) 1.在32位系统环境,编译选项为4字节对齐,那么sizeof(A)和sizeof(B)是多少? #pragma pack(4)st…...
mongodb源码分析session执行handleRequest命令find过程
mongo/transport/service_state_machine.cpp已经分析startSession创建ASIOSession过程,并且验证connection是否超过限制ASIOSession和connection是循环接受客户端命令,把数据流转换成Message,状态转变流程是:State::Created 》 St…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院挂号小程序
一、开发准备 环境搭建: 安装DevEco Studio 3.0或更高版本配置HarmonyOS SDK申请开发者账号 项目创建: File > New > Create Project > Application (选择"Empty Ability") 二、核心功能实现 1. 医院科室展示 /…...

Python实现prophet 理论及参数优化
文章目录 Prophet理论及模型参数介绍Python代码完整实现prophet 添加外部数据进行模型优化 之前初步学习prophet的时候,写过一篇简单实现,后期随着对该模型的深入研究,本次记录涉及到prophet 的公式以及参数调优,从公式可以更直观…...

Keil 中设置 STM32 Flash 和 RAM 地址详解
文章目录 Keil 中设置 STM32 Flash 和 RAM 地址详解一、Flash 和 RAM 配置界面(Target 选项卡)1. IROM1(用于配置 Flash)2. IRAM1(用于配置 RAM)二、链接器设置界面(Linker 选项卡)1. 勾选“Use Memory Layout from Target Dialog”2. 查看链接器参数(如果没有勾选上面…...

基于Docker Compose部署Java微服务项目
一. 创建根项目 根项目(父项目)主要用于依赖管理 一些需要注意的点: 打包方式需要为 pom<modules>里需要注册子模块不要引入maven的打包插件,否则打包时会出问题 <?xml version"1.0" encoding"UTF-8…...
【C++从零实现Json-Rpc框架】第六弹 —— 服务端模块划分
一、项目背景回顾 前五弹完成了Json-Rpc协议解析、请求处理、客户端调用等基础模块搭建。 本弹重点聚焦于服务端的模块划分与架构设计,提升代码结构的可维护性与扩展性。 二、服务端模块设计目标 高内聚低耦合:各模块职责清晰,便于独立开发…...
Mobile ALOHA全身模仿学习
一、题目 Mobile ALOHA:通过低成本全身远程操作学习双手移动操作 传统模仿学习(Imitation Learning)缺点:聚焦与桌面操作,缺乏通用任务所需的移动性和灵活性 本论文优点:(1)在ALOHA…...

云原生玩法三问:构建自定义开发环境
云原生玩法三问:构建自定义开发环境 引言 临时运维一个古董项目,无文档,无环境,无交接人,俗称三无。 运行设备的环境老,本地环境版本高,ssh不过去。正好最近对 腾讯出品的云原生 cnb 感兴趣&…...