全面深入理解MySQL自增锁

💗推荐阅读文章💗

  • 🌸JavaSE系列🌸👉1️⃣《JavaSE系列教程》
  • 🌺MySQL系列🌺👉2️⃣《MySQL系列教程》
  • 🍀JavaWeb系列🍀👉3️⃣《JavaWeb系列教程》
  • 🌻SSM框架系列🌻👉4️⃣《SSM框架系列教程》

🎉本博客知识点收录于🎉👉🚀《MySQL系列教程》🚀—>✈️03【锁、事务原理、MVCC】✈️

文章目录

    • 2.5 自增锁
      • 2.5.1 表的插入数据方式
      • 2.5.1 insert的不同类型
        • 1)Simple inserts
        • 2)Bulk inserts
        • 3)Mixed-mode
      • 2.5.2 自增锁原理
        • 1)插入原理
        • 2)自增锁表锁
      • 2.5.3 自增锁的模式
        • 1)traditional(传统模式)
        • 2)consecutive(连续模式)
        • 3)interleaved(交叉模式)
      • 2.5.4 自增步长控制

2.5 自增锁

MySQL的自增锁是指在使用自增主键(Auto Increment)时,为了保证==唯一性和正确性==,系统会对自增字段进行加锁。这样可以确保同时插入多条记录时,每条记录都能够获得唯一的自增值。

2.5.1 表的插入数据方式

我们之前在表中插入数据都是用最基本的insert,但insert语句的用法用很多,另外MySQL还提供replace语句,允许对表中的数据进行替换;

  • insert用法:
drop table if exists t3;CREATE TABLE `t3`  (`id` int(11) NOT NULL AUTO_INCREMENT,`age` int(11) NULL DEFAULT NULL,PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT=1;insert into t3 values(1,20);
insert into t3 values(2,25);drop table if exists t4;CREATE TABLE `t4`  (`id` int(11) NOT NULL AUTO_INCREMENT,`age` int(11) NULL DEFAULT NULL,PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT=1;-- 插入记录,如果存在这条记录就报错(主键唯一)
insert into t4 values(10,20);
insert into t4 values(11,20),(12,21),(13,22);
insert into t4 set id=14,age=25;
insert into t4 select * from t3;
  • replace用法:
delete from t4;-- 如果没有这条记录就新增,有这条记录就修改
replace into t4 values(1,20);  
replace into t4 set id=10,age=100 ;
replace into t4 select * from t3;

2.5.1 insert的不同类型

1)Simple inserts

简单插入模式

  • 示例:
insert into table_name values(xxx);
  • 特点:可以提前确定要插入的行数

2)Bulk inserts

批量插入模式,包含insert…select、replace select、load data等语句;

  • 示例:
insert into t4 select * from t3;
replace into t4 select * from t3;

Tips:load data属于海量数据插入,暂时不演示

  • 特点:事先不知道要插入的行数,以及所需的自动增量值的数量

3)Mixed-mode

该模式也属于Simple Inserts

  • 示例:
insert into table_name values(xxxx),(xxxx),(xxxx);
  • 特点:为一些(但不是全部)新行指定自动增量值

2.5.2 自增锁原理

1)插入原理

MySQL自增锁的实现机制是使用了一个名为"auto-increment lock"的互斥锁。当使用INSERT语句插入一条新记录时,MySQL会自动为自增字段加锁,防止其他并发的插入操作同时获取相同的自增值。这个锁是在内部实现的,不需要用户手动创建或管理。
自增锁确保了插入记录的唯一性和正确性,避免了并发插入产生冲突。但同时也会带来一些性能上的影响,因为并发插入操作需要等待锁的释放。因此,在高并发的场景下,可能需要考虑使用其他方案来避免自增锁成为瓶颈。

注意:自增锁跟事务无关,即使多个insert语句存在同一个事务中,每次insert都会申请最新的自增锁来获取最新的AUTO_INCREMENT值;自增锁保持到insert语句结束,而不是事务结束;

2)自增锁表锁

需要注意的是,自增锁是基于表级别的,而不是行级别的。这意味着在同一时刻针对于同一张表只能有一个线程在插入记录(前提是需要increment来分配id),并且每个表都有一个自己独立的自增锁。

2.5.3 自增锁的模式

和自增锁相关的一个参数为(5.1.22版本之后加入)innodb_autoinc_lock_mode:可以设定3个值,0,1,2

show variables like 'innodb_autoinc_lock_mode';

  • 0:traditional(传统模式):每次insert都会产生表级别的自增锁,能够绝对保证insert的插入顺序,但并发能力较弱;
  • 1:consecutive(连续模式):对于Simple Inserts能够产生一个轻量级的页面锁来保证insert的连续插入;对于Bulk Inserts无法确定插入的行数时采用表级别自增锁来保证insert的连续插入;
  • 2:interleaved(交叉模式):不采用表锁,来一个insert处理一个,并发能力最高,但可能会造成insert分配的id顺序不一致;

Tips:参数只控制InnoDB引擎的设置,所有MyISAM均为traditional ,每次均会进行表锁。只有Innodb会视参数不同而产生不通的锁。

1)traditional(传统模式)

在传统模式下,不管是在执行Simple inserts还是Bulk inserts时每个insert获取自增锁时都会触发表锁,在某个insert没有释放表锁之前其他线程/进程均不可获取自增锁;虽然传统模式保证了多个insert插入的连续性但实际上并发插入属于串行化,性能较低;

Tips:再次说明,自增锁是执行insert时获取auto_increment值时才会申请,获取到auto_increment值时就会立即释放,跟事务无关;

2)consecutive(连续模式)

在连续模式下,InnoDB会根据当前执行的insert语句来判断是否使用表级别自增锁。这也是InnoDB的默认值;

  • Simple inserts:InnoDB能够预先知道要插入的行数,因此产生的自增锁只会锁住对应的那些id(页锁),避免表级别的自增锁
  • Bulk Inserts:InnoDB无法预知要插入的行,触发表级别自增锁

【Simple Inserts】

【Bulk Inserts】

3)interleaved(交叉模式)

在交叉模式下,所有的insert语句都不会使用自增锁(悲观锁),而是采用一个轻量级的mutex(乐观锁),来一个insert立即处理,在生成insert语句完毕后检查id是否被其他线程/进程使用,如果已经被使用则重新获取id;这样一来,多条 INSERT 语句可以并发的执行,因此交叉模式并发量最高,但对于同一个语句来说它所得到的auto_increment值可能不是连续的。

  • 交叉模式示意图:


【模拟交叉模式并发插入情况】
步骤①:Thread-01线程执行insert获取到auto_increment值为10
步骤②:与此同时Thread-02线程也获取到10
步骤③:然后又回到Thread-01线程对auto_increment值+1,此时auto_increment为11
步骤④:然后Thread-02线程也对auto_increment+1,此时auto_increment为12
步骤⑤:Thread-01线程校验id值是否被其他线程使用过,校验结果:未被其他线程使用过,执行插入
步骤⑥:Thread-01线程校验id值是否被其他线程使用过,校验结果:已经被其他线程使用过,本次操作取消;
最终Thread-01线程先将auto_increment值写入插入字段中,Thread-02线程将auto_increment写入字段中发现该字段已经被其他线程使用过,因此本次操作取消;但auto_increment值已经变为12;下一次执行insert的线程获取auto_increment值将会获取到12,auto_increment为11这一次就这样跳过了;

【交叉模式的注意事项】
由于交叉模式所带来的id不连续问题,在搭建有MySQL主从复制的架构并且binlog日志格式为SBR时会出现主从数据不一致问题;
原因:当Master接收高并发量的insert语句时会将insert语句记录到binlog日志中,这些binlog日志被发送到Slave时Slave将会并发执行这些SQL语句,很有可能导致Slave执行这些语句的顺序和当初Master执行的顺序一致,导致主从分配的id不一致,因此在MySQL主从复制时从服务器应禁止使用交叉模式;

2.5.4 自增步长控制

一般我们在创建表的时候id起始值为1,通过AUTO_INCREMENT可以设置其值;

drop table if exists t3;
CREATE TABLE `t3`  (`id` int(11) NOT NULL AUTO_INCREMENT,`age` int(11) NULL DEFAULT NULL,PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT=1;-- 在创建表后也可以通过SQL语句修改auto_increment
alter table t3 auto_increment=20;

自增幅度由以下两个参数进行控制:

-- 自增的步长
set auto_increment_increment=2;			-- 默认1

可以通过函数获取最后一个插入的id:

select last_insert_id();

【测试】

session-01session-02
begin;
begin;
insert into t3 values(null,1);
insert into t3 values(null,1);
rollback;
commit;

最终session-02插入的那条记录id为2;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/5148.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【HarmonyOS】元服务隐私协议开发指导样例

【关键字】 隐私、弹窗、元服务、协议 【介绍】 每个元服务必须提供隐私声明,否则将导致提交元服务发布上架时,审核无法通过。隐私声明的具体要求请参见隐私声明规范。用户使用元服务前,必须引导其了解隐私声明信息,获取用户授权…

【NLP】一项NER实体提取任务

一、说明 从文本中提取实体是一项主要的自然语言处理 (NLP) 任务。由于深度学习(DL)的最新进展使我们能够将它们用于NLP任务,并且与传统方法相比,在准确性上产生了巨大的差异。 我试图使用深度学习和传统方法从文章中提取信息。结果是惊人的,因为DL方法…

tcpdump 使用

Linux tcpdump抓包工具使用 tcpdump官网tcpdump使用tcpdump抓取http请求 tcpdump官网 官网 请参考官网参看具体参数信息 tcpdump使用 tcpdump抓取http请求 http请求抓取参考网址 //抓取HTTP GET (GET 0x47, 0x45, 0x54, 0x20) 请求,以ascii展示 tcpdump -i eth0 -A -s 0 …

C#被指定窗体的MdiParent的窗体不是MdiContainer

工作的时候遇到一个问题: 被指定窗体的MdiParent的窗体不是MdiContainer 这个问题的原因是父窗体的IsMdiContainer 属性设置为false导致的。将此属性设置为true,即可解决此问题。有两种方式设置窗体的IsMdiContainer 属性。 第一种,在父窗口…

Chrome远程调试webview

网址 谷歌远程调试解决方案 https://blog.csdn.net/m0_56516186/article/details/131260563Chrome远程调试webview https://blog.csdn.net/weixin_44801980/article/details/117755550

Editing Large Language Models: Problems, Methods, and Opportunities

本文是LLM相关的系列文章,针对《Editing Large Language Models: Problems, Methods, and Opportunities》的翻译。 编辑大语言模型:问题、方法和机遇 摘要1 引言2 问题定义3 当前方法3.1 保留LLM参数的方法3.2 修改LLM参数的方法 4 初步实验4.1 数据集…

python实现拼多多商品详情接口API

最近工作需要用到拼多多的一些接口,官方竟然没有提供,python的sdk,于是就自己简单的写了一个商品SKU接口的api。 1、代码 #!/usr/bin/python3# -*- coding: utf-8 -*-# Time : 2020/3/29 0021 下午 19:40# Author : xiaozhi!…

201. 数字范围按位与 Python

文章目录 一、题目描述示例 1示例 2示例 3 二、代码三、解题思路 一、题目描述 给你两个整数 left 和 right ,表示区间 [left, right] ,返回此区间内所有数字 按位与 的结果(包含 left 、right 端点)。 示例 1 输入&#xff1a…

「深度学习之优化算法」(十六)万有引力算法

1. 万有引力算法简介 (以下描述,均不是学术用语,仅供大家快乐的阅读) 万有引力算法(Gravitational Search Algorithm)是受物体之间的万有引力启发而提出的算法。算法提出于2008(2009)年,时间不长,不过相关的文章和应用已经相对较多,也有不少的优化改进方案。   万…

apple pencil二代平替笔哪个好用?苹果平板平替笔排行

光是一款Apple Pencil,就卖到了接近一千多块,信息对于很多人来说都觉得太贵了。事实上,由于平替电容笔的性价比也非常高,因此它还是值得一试的。不管是学习,写作,还是绘画,这支平替电容笔&#…

自洽性改善语言模型中的思维链推理7.13、7.14

自洽性改善语言模型中的思维链推理 摘要介绍对多样化路径的自洽实验实验设置主要结果当CoT影响效率时候,SC会有所帮助与现有方法进行比较附加研究 相关工作总结 原文: 摘要 本篇论文提出了一种新的编码策略——自洽性,来替换思维链中使用的…

AI绘画 | 迷人武士美少女战士作品集

今天用Midjourney生成了质量极高的美少女武士后续会作为固定栏目来分享美图接下来请欣赏作品 提示词分享:1.an asian girl dressed in samurai style, in the style of anime aesthetic, trick of the eye paintings, dollcore, light red and black, resin, 8k, ex…

数据结构--图的基本操作

数据结构–图的基本操作 使用的存储模式&#xff1a; 图的基本操作&#xff1a; • Adjacent(G,x,y)&#xff1a;判断图G是否存在边<x, y>或(x, y)。 • Neighbors(G,x)&#xff1a;列出图G中与结点x邻接的边。 • InsertVertex(G,x)&#xff1a;在图G中插入顶点x。 • …

Apache HTTPD 多后缀解析漏洞

Apache HTTPD 多后缀解析漏洞 一、环境搭建二、漏洞原理三、漏洞复现 一、环境搭建 如下介绍kali搭建的教程 cd ~/vulhub/httpd/apache_parsing_vulnerability // 进入指定环境 docker-compose up -d // 启动环境docker-compose ps使用这条命令查看当前正在运行的环境 打开…

Java入门

目录 一、程序 什么是程序 二、计算机编程语言 1.计算机语言是什么 Java历史 特点 执行机制 计算机执行机制 Java的执行机制 三、JDK安装 名词解释 安装与校验 配置环境变量 四、第一个Java程序 编写代码 编译运行 规范 六、Java核心机制&#xff1a;JVM 1.…

【C语言】memcpy,memmove,memcmp,memset函数详解

memcpy,memmove,memcmp,memset函数详解 memcpy函数一、 memcpy函数的定义&#xff1a;二、memcpy函数的功能&#xff1a;三、memcpy函数模拟memcpy注意事项 memmove函数一、memmove函数简介二、memmove函数的模拟1.两种情况2模拟实现 memcmp函数memecmp函数介绍 memset函数mems…

数据结构(王道)——线性表的存储结构之双链表

双链表和单链表的对比 一、从无到有创建一个双链表及其基础操作 带头结点 的双链表 初始化 双链表的后插操作&#xff1a; 从后插可以拓展到按位序插入&#xff0c;和前插操作。 因为双链表的特性&#xff0c;如果按位序插入或者前插操作&#xff0c;只需要找到插入的位置的前…

基于SpringBoot + EasyExcel + Vue + Blob实现导出Excel文件的前后端完整过程

首先前端发起HTTP请求之后&#xff0c;后端返回一个Excel输出流&#xff0c;然后前端用Blob类型接收数据&#xff0c;并且解析响应头数据以及提取源文件名&#xff0c;最后用a标签完成下载。 一、后端代码 &#xff08;1&#xff09;导入阿里巴巴的EasyExcel依赖&#xff08;…

不依赖yacc如何实现表达式按优先级解析

总结 无意发现一个非常有意思的简单语法解析器&#xff0c;不依赖lex/yacc&#xff0c;本文对其中比较难理解的表达式解析&#xff08;带优先级&#xff09;部分做一些分析和记录。 &#xff08;理解本文需要调试后面的代码部分&#xff0c;have fun&#xff01;&#xff09;…

219. 存在重复元素 II

给你一个整数数组 nums 和一个整数 k &#xff0c;判断数组中是否存在两个 不同的索引 i 和 j &#xff0c;满足 nums[i] nums[j] 且 abs(i - j) < k 。如果存在&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 示例 1&#xff1a; 输入&#xff1a;num…