MySQL | 行锁——记录锁、间隙锁 、临键锁、插入意向锁

news2024/11/11 19:21:33

1、InnoDB中的行锁

行锁(Row Lock) 也称为记录锁,顾名思义,就是锁住某一行(某条记录row)。需要注意的是,MySQL服务器层并没有实现行锁机制,行级锁只在存储引擎层实现

优点:锁定力度小,发生锁冲突概率低,可以实现的并发度高

缺点:对于锁的开销比较大,加锁会比较慢,容易出现死锁情况。

InnoDB与MyISAM的最大不同有亮点:一是支持事务;二是采用了行级锁。

1、记录锁(Record Locks)

记录锁页就是仅仅把一条记录锁上,官方的类型名称为:Lock_REC_NOT_GAP。比如把id值为1的那条记录加一个记录锁。仅仅是锁住了id值为1的记录,对其他行的数据没有影响。

记录锁是有S锁和X锁之分的,称之为S型记录锁X型记录锁

  • 当一个事务获取了一条记录的S型记录锁后,其他事务也可以继续获取该记录的S型记录锁,但不可以继续获取X型记录锁;
  • 当一个事务获取了一条记录的X型记录锁后,其他事务既不可以继续获取该记录的S型记录锁,也不可以继续获取X型记录锁。

举例:记录锁的使用场景模拟

场景1:事务1开启S锁,事务2开始S锁并且尝试获取X型记录锁

事务1:开启S锁

mysql> begin;
Query OK, 0 rows affected (0.01 sec)

mysql> select * from user where id = 1 lock in share mode;
+----+---------+
| id | name    |
+----+---------+
|  1 | 张三3   |
+----+---------+
1 row in set (0.00 sec)

事务2:开启S锁,尝试获取X锁

mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from user where id  = 1 lock in share mode;
+----+---------+
| id | name    |
+----+---------+
|  1 | 张三3   |
+----+---------+
1 row in set (0.00 sec)

mysql> update user set name = "张三4" where id = 1;

此时事务2获取S锁成功,获取X锁失败进行阻塞状态。

场景2:事务1开启X锁,事务2尝试获取X锁和S锁

事务1:开启X锁

mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from user where id  = 1 for update;
+----+---------+
| id | name    |
+----+---------+
|  1 | 张三3   |
+----+---------+
1 row in set (0.00 sec)

事务2:尝试获取X锁和S锁

mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from user where id = 1 ;
+----+---------+
| id | name    |
+----+---------+
|  1 | 张三3   |
+----+---------+
1 row in set (0.00 sec)

mysql> select * from user where id = 1 for update;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
mysql> update user set name = "张三10" where id = 1;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
mysql> 

事务2获取X锁和S锁失败,进入阻塞

场景3:事务1对id值为1的进行加S锁,事务2对id值的5的加X锁。

事务1:开启S锁

mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from user where id = 1 lock in share mode;
+----+---------+
| id | name    |
+----+---------+
|  1 | 张三3   |
+----+---------+
1 row in set (0.00 sec)

事务2:获取X锁

mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> update user set name = "王五2" where id = 5;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

事务2获取X锁成功。如果对同一行记录进行加锁则事务2获取X锁失败,对不同的行进行加锁则互不影响。

2、间隙锁 (Gap Locks)

MySQLREPEATABLE READ 隔离级别下是可以解决幻读问题的,解决方案有两种,可以使用 MVCC 方案解决,也可以采用加锁 方案解决。但是在使用加锁方案解决时有个大问题,就是事务在第一次执行读取操作时,那些幻影记录尚不存在,我们无法给这些幻影记录加上记录锁。InnoDB提出了一种称之为 **Gap Locks **的锁,官方的类型名称为: LOCK_GAP ,我们可以简称为 gap锁。比如,把id值为8的那条记录加一个gap锁的示意图如下。

id1358
name李四张三王五赵六

图中id值为8的记录加了gap锁,意味着**不允许别的事务在id值为8的记录前边的间隙插入新记录 **,其实就是id列的值(5,8)这个区间的新记录是不允许立即插入的。比如,有另外一个事务再想插入一条id值为6的新记录,它定位到该条新记录的下一条记录的id值为8,而这条记录上又有一个gap锁,所以就会阻塞插入操作,直到拥有这个gap锁的事务提交了之后,id列的值在区间(5,8)中的新记录才可以被插入。
gap锁的提出仅仅是为了防止插入幻影记录而提出的。虽然有 共享gap锁 独占gap锁 这样的说法,但是它们起到的作用是相同的。而且如果对一条记录加了gap锁(不论是共享gap锁还是独占gap锁),并不会限制其他事务对这条记录加记录锁或者继续加gap锁。

举例:间隙锁的使用场景模拟

事务1:加S锁

mysql> select * from user;
+----+------------+
| id | name       |
+----+------------+
|  1 | 张三3      |
|  3 | 张胜男2    |
|  5 | 王五2      |
|  8 | 赵六       |
| 10 | 张三10     |
+----+------------+
5 rows in set (0.00 sec)
mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from user where id = 6 lock in share mode;
Empty set (0.00 sec)

mysql> 

事务2:加X锁

mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from user where id = 6 for update;
Empty set (0.00 sec)

mysql> 

事务3:新增数据

mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> insert into user (`id`,`name`) values (7,"李四33");
^C^C -- query aborted
ERROR 1317 (70100): Query execution was interrupted
mysql> insert into user (`id`,`name`) values (2,"李四33");
Query OK, 1 row affected (0.00 sec)

间隙锁加的是6,所以间隙范围是5-8,新增id为7则失败,新增id为2则成功。

3、临键锁 (Next-Key Locks)

有时候我们既想 锁住某条记录 ,又想 阻止其他事务在该记录前边的 间隙插入新记录,所以innoDB就提出了一种称之为Next-Key Locks的锁,官方的类型名称为: LOCK_ORDINARY,我们也可以简称为next-key锁。Next-KeyLocks是在存储引擎 innodb 、事务级别在 **可重复读 **的情况下使用的数据库锁,innodb默认的锁就是Next-Keylocks。

next-key锁 的本质就是一个 记录锁 和一个 gap锁 的合体,它既能保护该条记录,又能阻止别的事务将新记录插
入被保护记录前边的 间隙

举例:临键锁的使用场景模拟

事务1:加X锁

mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from user where id <=8 and id >5 for update;
+----+--------+
| id | name   |
+----+--------+
|  8 | 赵六   |
+----+--------+
1 row in set (0.00 sec)

事务2:尝试获取X锁和S锁,并且尝试插入数据

mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from user where id = 8 lock in share mode;
^C^C -- query aborted
ERROR 1317 (70100): Query execution was interrupted
mysql> select * from user where id = 8 for update;
^C^C -- query aborted
ERROR 1317 (70100): Query execution was interrupted
mysql> insert into user (id,name) values (7,"李四2323");
^C^C -- query aborted
ERROR 1317 (70100): Query execution was interrupted

事务2都需要进行等待,满足间隙锁和记录锁要求

4、插入意向锁(Insert Intention Locks)

我们说一个事务在 插入 一条记录时需要判断一下插入位置是不是被别的事务加了 gap锁 (next-key锁 也包含gap锁),如果有的话,插入操作需要等待,直到拥有 gap锁 的那个事务提交。但是InnoDB规定事务在等待的时候也需要在内存中生成一个锁结构,表明有事务想在某个 间隙插入新记录,但是现在在等待。InnoDB就把这种类型的锁命名为Insert Intention Locks,官方的类型名称为:LOCK_INSERT_INTENTION,我们称为插入意向锁 。插入意向锁是一种 Gap锁,不是意向锁,在insert操作时产生。
插入意向锁是在插入一条记录行前,由
INSERT 操作产生的一种间隙锁
。该锁用以表示插入意向,当多个事务在同一区间(gap)插入位置不同的多条数据时,事务之间不需要互相等待。假设存在两条值分别为4和7的记录,两个不同的事务分别试图插入值为5和6的两条记录,每个事务在获取插入行上独占的(排他)锁前,都会获取(4,7)之间的间隙锁,但是因为数据行之间并不冲突,所以两个事务之间并不会产生冲突(阻塞等待)。总结来说,插入意向锁的特性可以分成两部分:

  1. 插入意向锁是一种特殊的间隙锁– 间隙锁可以锁定开区间内的部分记录,
  2. 插入意向锁之间互不排斥,所以即使多个事务在同一区间插入多条记录,只要记录本身(主键、唯一索引)不冲突,那么事务之间就不会出现冲突等待。

注意,虽然插入意向锁中含有意向锁三个字,但是它并不属于意向锁而属于间隙锁,因为意向锁是表锁而插入意向锁是行锁

在这里插入图片描述

从图中可以看到,由于T1持有gap锁,所以T2和T3需要生成一个插入意向锁的锁结构并且处于等待状态。当T1提交后会把它获取到的锁都释放掉,这样T2和T3就能获取到对应的插入意向锁了(本质上就是把插入意向锁对应锁结构的is_waiting属性改为false)T2和T3之间也并不会相互阻塞,它们可以同时获取到id值为8的插入意向锁,然后执行插入操作。事实上插入意向锁并不会阻止别的事务继续获取该记录上任何类型的锁。

举例:插入意向锁的使用场景模拟

场景:事务1开启间隙锁,事务2和事务3分别插入数据,在事务1不提交之前,事务2和事务3都是进入阻塞状态,直到事务1提交,事务2和事务3同时成功

事务1:开启间隙锁

mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from user where id = 6 for update;
Empty set (0.00 sec)

事务2:插入数据

mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> insert into user (id,name) values (7,"李四2323");
Query OK, 1 row affected (34.91 sec)

事务3:插入数据

mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> insert into user (id,name) values (6,"李四2323");
Query OK, 1 row affected (6.35 sec)

事务1未提交,事务2和事务3进入阻塞状态,事务1提交,事务2和事务3则新增成功

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

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

相关文章

秒懂Linux之进程调度与切换

目录 一.进程的切换 二.进程的调度 基本走向 调度算法 一.进程的切换 进程在运行的时候并非是放在cpu上让其全部跑完&#xff0c;而是基于时间片&#xff08;比如每1ms就切换一个进程&#xff09;进行轮转进行的~ 竞争性: 系统进程数目众多&#xff0c;而CPU资源只有少量&…

解决端口号被占用问题

第一种&#xff1a; 最简单有效的方法&#xff0c;重启一下电脑&#xff0c;占用此端口的程序就会释放端口。 第二种&#xff1a; 使用命令找到占用端口的程序&#xff0c;把它关闭。 1、打开运行窗口输入&#xff1a;CMD &#xff0c;进入命令窗口。 2、输入&#xff1a;n…

【Mind+】 掌控板入门教程09 魔法之光

光是地球生命的来源&#xff0c;是人类生活的依据&#xff0c;更是人类认识外部世界的工具。在科技发达的今天&#xff0c;我们可以通过传感器来检测光&#xff0c;利用光帮助我们更好的生活。 今天就让我们一起通过几个小项目来感受光的魔法吧。 项目示例 掌控板…

基于vue框架的《程序设计》在线学习平台的设计与实现adl42(程序+源码+数据库+调试部署+开发环境)系统界面在最后面。

系统程序文件列表 项目功能&#xff1a;学生,教师,课程信息,课程类型,班级,课程文件,学生选课,移除选课,课程作业,作业提交,作业批改 开题报告内容 基于Vue框架的《程序设计》在线学习平台的设计与实现——开题报告 一、选题背景与意义 1. 选题背景 随着互联网技术的不断发…

数据库事务的四大特性ACID

数据库事务的四大特性ACID 数据库事务&#xff08;Transaction&#xff09;是数据库管理系统&#xff08;DBMS&#xff09;执行过程中的一个逻辑单位&#xff0c;由一个或多个SQL语句组成&#xff0c;这些语句作为一个整体一起向系统提交&#xff0c;要么全部执行&#xff0c;…

MP4 H.264 MPEG-4 MPEG-2

MP4 视频编解码技术 H.264 MPEG-4 MPEG-2 MP4 (MPEG-4 Part 14): Format: A digital multimedia container format.Use: Often used to store video, audio, subtitles, and still images.Compression: Can use different codecs, such as H.264, for video compression. H.264…

linux中的库的概念、动态库与静态库

1.为什么引用库 准备头文件、源文件和主程序文件 g 将源程序进行联合编译生成可执行出程序 ./exec执行可执行程序 在上述案例中&#xff0c;主程序要是有的源程序代码&#xff0c;在add.cpp中&#xff0c;如果项目结束后&#xff0c;到了交付阶段&#xff0c;由于主程序的生…

WPF篇(13)-ScrollViewer控件+ScrollBar滚动条+Slider滑动条

ScrollViewer控件 如果某个控件的尺寸太大&#xff0c;当前界面无法全部显示&#xff0c;则可以将这个控件包含在ScrollViewer中&#xff0c;因为ScrollViewer控件封装了一个水平滚动条ScrollBar和一个垂直滚动条ScrollBar&#xff0c;所以&#xff0c;ScrollViewer就是一个包…

基于llama.cpp实现Llama3模型的guff格式转换、4bit量化以及GPU推理加速(海光DCU)

重要说明&#xff1a;本文从网上资料整理而来&#xff0c;仅记录博主学习相关知识点的过程&#xff0c;侵删。 序言 本文使用llama.cpp框架&#xff0c;对 Llama3-8B-Instruct 模型进行gguf格式转换&#xff0c;8bit量化&#xff0c;并在CPU和GPU上对8bit模型进行推理。 测试…

5.5.transformer

Transformer ​ Transformer是由编码器和解码器组成的&#xff0c;基于自注意力的模块叠加而成的&#xff0c;源(输入)序列和目标(输出)序列的嵌入(embedding)表示将加上位置编码在分别输入到编码器和解码器中&#xff1a; ​ ​ 从宏观角度来看&#xff0c;Transformer的编码…

Elastic 8.15:更好的语义搜索、新的 OTel 分布、SIEM 数据导入

作者&#xff1a;来自 Elastic Brian Bergholm 今天&#xff0c;我们很高兴地宣布 Elastic 8.15 正式发布。 有什么新功能&#xff1f; 8.15 版本包含大量新功能&#xff0c;包括更多工具来优化相关性、增强模型的灵活性和改进向量搜索&#xff0c;以及在 AI 驱动的安全分析方…

学习大数据DAY35 利用 echarts 的开源图表和 python 异常处理优化网站

目录 根据分数统计电影数量来生成图表 上机练习 14 添加异常 添加电影类型判断是整数及正整数异常 部署项目到 Nginx 上机练习 15 根据分数统计电影数量来生成图表 Echarts 官网&#xff1a; https://echarts.apache.org/examples/zh/index.html 下载柱状图和饼图 可以…

访问网站显示不安全如何处理

当访问网站时浏览器提示“不安全”&#xff0c;这通常是由于多种原因造成的。下面是一些常见的原因及其解决办法&#xff1a; 未启用HTTPS协议 如果网站仅使用HTTP协议&#xff0c;数据传输没有加密&#xff0c;会被浏览器标记为“不安全”。解决办法是启用HTTPS协议&#xff…

C++(4):基类-派生类

基类—>派生类 先构造基类再构造派生类 匿名对象形式向基类传参&#xff0c;基类先构造先传参 复制构造函数&#xff0c;采用类型兼容性规则即用派生类代替基类 使用protect派生类可访问其它地方不能访问 private只能自己访问 p访问的是自己类里的showTime 类型兼容性规则&…

HCIP | 实验二

概述 要求&#xff1a; 1.如图连接&#xff0c;合理规划IP地址&#xff0c;所有路由器各自创建一个loopback接口 2.R1再创建三个接口IP地址为201.1.1.1/24、201.1.2.1/24、201.1.3.1/24 R5再创建三个接口IP地址为202.1.1.1/24、202.1.2.1/24、202.1.3.1/24 R7再创建三个接口…

Mac平台M1PRO芯片MiniCPM-V-2.6网页部署跑通

Mac平台M1PRO芯片MiniCPM-V-2.6网页部署跑通 契机 ⚙ 2.6的小钢炮可以输入视频了&#xff0c;我必须拉到本地跑跑。主要解决2.6版本默认绑定flash_atten问题&#xff0c;pip install flash_attn也无法安装&#xff0c;因为强制依赖cuda。主要解决的就是这个问题&#xff0c;还…

批发行业进销存-入库单表格识别 源码CyberWinApp-SAAS 本地化及未来之窗行业应用跨平台架构

一、进销存入库进货单单识别意义 对个人、商品、公示内容等纸质信息登记表进行识别&#xff0c;用于登记信息的结构化整理和统计&#xff0c;大幅度降低人力录入成本&#xff0c;提升信息管理的便捷性 1. 提高效率&#xff1a;自动转换节省了手动录入的时间和精力&#xff0c;…

实景视频可视化的结构化脚本,脚本分为三类:文字脚本,分镜头脚本和动态脚本

在视频创作的世界中&#xff0c;脚本是创作的基础和核心。无论是简短的广告视频&#xff0c;还是复杂的电影制作&#xff0c;脚本都扮演着不可或缺的角色。随着视频内容需求的多样化&#xff0c;结构化脚本逐渐成为确保创作效率和质量的重要工具。结构化脚本不仅帮助创作者清晰…

PythonStudio 控件使用常用方式(十八)TCategoryButtons

PythonStudio是一个极强的开发Python的IDE工具&#xff0c;它使用的是Delphi的控件&#xff0c;常用的内容是与Delphi一致的。但是相关文档并一定完整。现在我试试能否逐步把它的控件常用用法写一点点&#xff0c;也作为PythonStudio的参考。 从1.2.1版开始&#xff0c;Python…

Elastic Search 8.15:通过语义文本和重新排序实现可访问的语义搜索

作者&#xff1a;来自 Elastic Nick Chow, Sunayana Vatassery 在 8.15 中&#xff0c;我们的客户可以更轻松地获得出色的搜索结果。我们的最新版本带来了语义重新排名&#xff08;semantic reranking&#xff09;、额外的向量搜索工具和更多第三方模型提供商&#xff0c;并将我…