MySQL行级锁——技术深度+1

引言

本文是对MySQL行级锁的学习,MySQL一直停留在会用的阶段,需要弄清楚锁和事务的原理并DEBUG查看。

PS:本文涉及到的表结构均可从https://github.com/WeiXiao-Hyy/blog中获取,欢迎Star!

MySQL行级锁

行级锁(Row-Level-Locking)是InnoDB引擎特有的特性

  • 共享锁(S锁):一个事务去加共享锁后,同时也允许其他事务读,但是排斥其他事务获取排他锁(X锁)
  • 排他锁(X锁):一个事务加排他锁后,其他事务不允许加X锁,也不允许加S锁。

不同的语句会加上不同的锁

  • insert,update,delete,select… for update (X锁)
  • select (不会加锁,快照读)
  • select… for share (S锁)

MySQL中行级锁

  • 记录锁(Record Lock)
  • 间隔锁(Gap Lock)
  • 临键锁(Next-Keys Lock)

行级锁并非是将锁加到记录上,而是加到了索引上

InnoDB引擎在RR事务隔离级别下使用临键锁搜索和索引扫描,从而防止幻读,该给索引记录上什么样的锁,要根据具体情况而定,不过MySQL都是首先考虑临键锁,根据不同的情况退化为记录锁或者间隙锁。

InnoDB引擎在RR事务隔离级别下使用临键锁搜索和索引扫描,从而防止幻读,索引当分析一个SQL加什么行级锁的时候要使用考虑以下几件事:

  1. 临键锁区间情况
  2. 通过条件确定索引数据范围,判断命中了哪些临键锁区间
  3. 判断是否可能退化为记录锁或者间隙锁
mysql> CREATE TABLE `t1` (
    ->   `id` int NOT NULL AUTO_INCREMENT,
    ->   `name` varchar(10) NOT NULL,
    ->   `id_nbr` varchar(19) DEFAULT NULL,
    ->   `age` int NOT NULL,
    ->   PRIMARY KEY (`id`),
    ->   UNIQUE KEY `idx_uk_id_nbr` (`id_nbr`),
    ->   KEY `idx_name` (`name`)
    -> ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
Query OK, 0 rows affected (0.02 sec)

mysql> insert into t1 values(3, '刘备', '110101193007282815', 93), (5, '孙权', '110101194007281016', 93), (6, '曹操', '110101191807288714', 95), (9, '王朗', '110101190007287516', 123);
Query OK, 4 rows affected (0.00 sec)
Records: 4  Duplicates: 0  Warnings: 0

mysql> select * from t1;
+----+--------+--------------------+-----+
| id | name   | id_nbr             | age |
+----+--------+--------------------+-----+
|  3 | 刘备   | 110101193007282815 |  93 |
|  5 | 孙权   | 110101194007281016 |  93 |
|  6 | 曹操   | 110101191807288714 |  95 |
|  9 | 王朗   | 110101190007287516 | 123 |
+----+--------+--------------------+-----+
4 rows in set (0.00 sec)

聚簇索引

记录存在

  • select * from t1 where id <= 3 for update; -> LOCK_MODE: X(临键锁), (-∞,3]
    请添加图片描述
  • select * from t1 where id < 3 for update; -> LOCK_MODE: X,GAP(间隔锁), (-∞,3)
    请添加图片描述
  • select * from t1 where id = 3 for update; -> LOCK_MODE: X,REC_NOT_GAP(记录锁), [3,3]
    请添加图片描述
  • select * from t1 where id <= 3 for share; -> LOCK_MODE: S,REC_NOT_GAP(共享锁)

请添加图片描述

记录不存在

  • select * from t1 where id = 7 for update;

由于id=7会落在(6,9]这个区间,但是查询条件没有9,因此退化为间隔锁,锁的范围为(6,9)
请添加图片描述

  • select * from t1 where id = 10 for update;

由于上边界索引key值不存在的时候,锁为临键锁,锁的范围为(9, +∞) LOCK_DATA=supremum pseudo-record
请添加图片描述

  • select * from t1 where id <= 4 for update;

命中了两个临键区(-∞,3]和(3,5], 第一个临键区不会退化,所以会加上一个上界=3的临键锁,对于第二个临键区,查询条件中不包含5,所有退化为间隔锁(3,5)
请添加图片描述

  • select * from t1 where id > 6 and id ≤ 9 for update;

刚刚好命中(6,9]临键区,但实际上会添加上一个最大索引记录值LOCK_DATA=supremum pseudo-record 原因当扫描到9(最大索引值)之后,还会继续向后扫描。即为(6,9]+(9,+∞)
请添加图片描述

二级唯一索引

二级唯一索引都是使用临键区和索引数据。

非聚簇唯一索引范围查询:InnoDB存储引擎使用临键锁搜索数据,会搜索到下一个不满足条件的索引KEY,如果进入到下一个临键区,则会将下一个临键区加上临键锁(任何时候都不会退化,这跟主键索引是不同的)

  • select * from t1 where id_nbr <= ‘110101190007287516’ for update;
    请添加图片描述
    id_nbr <= '110101190007287516’会进入到下一个临主键区,并且不会退化;

对于为什么会锁住该记录的主键值

如果不对主键索引加锁,并发操作就能通过id_nbr之外的条件修改id_nbr = '110101190007287516'的记录。比如:delete from t1 where name = '王朗’;

  • select * from t1 where id_nbr < ‘110101190007287516’ for update;

id_nbr < '110101190007287516’不会进入到下一个临主键区,并且不会退化;

请添加图片描述

  • select * from t1 where id_nbr = ‘110101190007287516’ for update;

如果条件只是等于一个已经存在的记录110101190007287516,则会退化为记录锁。

请添加图片描述

  • select * from t1 where id_nbr != ‘110101190007287515’ for update;

如果条件只是等于一个不存在的记录110101190007287516,则会退化为间隔锁。

请添加图片描述

二级普通索引

二级普通索引唯一不同的在于等值查询

  • select * from t1 where name = ‘caocao’ for update;

正常来说会命中临键区(-∞, caocao],然后退化为记录锁。但是实际上普通索引是允许重复,记录锁会导致出现幻读,结果为

  1. 临键区不退化
  2. 第二个退化为间隔锁

请添加图片描述

补充

查看MySQL的隔离级别

select @@transaction_isolation;

查看MySQL8.0的锁

SELECT * FROM performance_schema.data_locks;

SELECT OBJECT_SCHEMA, OBJECT_NAME, INDEX_NAME, LOCK_TYPE, LOCK_MODE, LOCK_STATUS, LOCK_DATA FROM performance_schema.data_locks;

参考资料

  • https://juejin.cn/post/7260059106765307961
  • https://book.douban.com/subject/35231266/
  • https://juejin.cn/post/7260070602613456957
  • https://juejin.cn/post/7170707711208718344

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

案例研究 | JumpServer助力天虹股份构建可靠的运维安全审计平台

天虹数科商业股份有限公司&#xff08;以下简称为“天虹股份”&#xff09;成立于1984年&#xff0c;是国有控股的上市公司。通过人本、科学的管理&#xff0c;以及专业、高效的运营&#xff0c;天虹股份连续多年入围中国连锁百强企业&#xff0c;拥有全国领先的零售技术研发和…

vue3 项目启动时vite版本问题报错

背景&#xff1a; 我是在项目迁移过程中遇到的这个问题&#xff0c;前提可以看下面这篇 http://t.csdnimg.cn/g70Eq 问题描述 迁移项目时&#xff0c;将项目整体升级到了vue3版本&#xff0c;启动项目时出现下列报错&#xff1a; npm ERR! Found: vite5.1.4 npm ERR! node_…

2024-2.基础操作-Python

Jupiter基本使用 cell有两种模式&#xff1a; codemarkdown 快捷键 新建cell&#xff1a;a,b删除cell&#xff1a;dd&#xff0c;x运行cell&#xff1a;shiftenter切换cell模式&#xff1a; m&#xff1a;将code模式的cell切换到mdy:将md模式的cell切换到code 智能补全&#x…

QT Webengine开发过程报错qml: Render process exited with code 159 (killed)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、解决方法二、补充说明总结 前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; 基于QT的Webengine开发过程中&#xff0c;QT的官方示例…

【算法】反转链表

本题来源---《反转链表》 题目描述&#xff1a; 给你单链表的头节点 head &#xff0c;请你反转链表&#xff0c;并返回反转后的链表。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5] 输出&#xff1a;[5,4,3,2,1]示例 2&#xff1a; 输入&#xff1a;head [1,2] 输…

22长安杯电子取证复现(检材一,二)

检材一 先用VC容器挂载&#xff0c;拿到完整的检材 从检材一入手&#xff0c;火眼创建案件&#xff0c;打开检材一 1.检材1的SHA256值为 计算SHA256值&#xff0c;直接用火眼计算哈希计算 9E48BB2CAE5C1D93BAF572E3646D2ECD26080B70413DC7DC4131F88289F49E34 2.分析检材1&am…

50.HarmonyOS鸿蒙系统 App(ArkUI)web组件实现简易浏览器

50.HarmonyOS鸿蒙系统 App(ArkUI)web组件实现简易浏览器 配置网络访问权限&#xff1a; 跳转任务&#xff1a; Button(转到).onClick(() > {try {// 点击按钮时&#xff0c;通过loadUrl&#xff0c;跳转到www.example1.comthis.webviewController.loadUrl(this.get_url);} …

Root mapping definition has unsupported parameters: [all : {analyzer=ik_max_wor

你们好&#xff0c;我是金金金。 场景 我正在使用Springboot整合elasticsearch&#xff0c;在创建索引(分词器) 运行报错&#xff0c;如下 排查 排查之前我先贴一下代码 import org.elasticsearch.action.admin.indices.create.CreateIndexRequest; // 注意这个包SpringBootTe…

Linux中如何安装ImageMagick及其常规使用命令

在Linux中安装ImageMagick可以通过包管理工具进行安装。具体步骤如下&#xff1a; 打开终端&#xff08;Terminal&#xff09;。 使用以下命令更新系统软件包列表&#xff1a; sudo apt update使用以下命令安装ImageMagick&#xff1a; sudo apt install imagemagick安装完…

物理机安装centos7并配置基本环境,网络配置,docker配置

1.首先下载镜像Download 2.下载UltraISO 安装docker 第1步&#xff1a;卸载当前版本docker yum erase docker \docker-client \docker-client-latest \docker-common \docker-latest \docker-latest-logrotate \docker-logrotate \docker-selinux \docker-engine-selinux \do…

[生活][杂项] 如何正确打开编织袋

编织袋打开的正确姿势 面对单线分离右边的线头&#xff0c;然后依次拉开即可

YAML教程-1-基础入门

领取资料&#xff0c;咨询答疑&#xff0c;请➕wei: June__Go YAML简介 YAML&#xff08;YAML Aint Markup Language&#xff09;是一种用于数据序列化的人类可读格式。它广泛用于配置文件、数据交换、持续集成/持续部署&#xff08;CI/CD&#xff09;等领域。YAML的设计目标…

注意,把Python库安装在一个环境里,可能会“非常危险”!

如果说谁写Python不用第三方库&#xff0c;我敬他是条汉子。如今到处是轮子的时代&#xff0c;Python第三方库管理成了开发者们头疼的问题。 可能在看这篇文章的很多人&#xff0c;都没用过Python虚拟环境&#xff0c;不知道安装Python库需要考虑版本兼容问题。 那么把所有要…

基于SpringBoot的健身房管理系统

一.前言 本系统用了 Sping Data JPA 这一不常用的数据库框架&#xff0c;是一个值得学习研究的点。 本项目用户名&#xff1a;admin 密码: admin123 方可进入。项目源码在文章开头&#xff0c;下载到本地导入IDEA&#xff0c;修改配置文件中数据库连接信息后&#xff0c;导入项…

字段名称导致mybatisplus自带方法报错.BadSqlGrammarException: ### Error querying database. C

今天在建一个数据表之后&#xff0c;在springboot中使用了mybatisplus代码生成工具生成了java相关代码&#xff0c;在查询的时候&#xff0c;使用的是list()方法查询&#xff0c;发现居然会报错&#xff0c;找了好久。 org.springframework.jdbc.BadSqlGrammarException: ###…

锁策略和死锁问题

锁策略 乐观锁 vs 悲观锁重量级锁 vs 轻量级锁自旋锁 vs 挂起等待锁读写锁 vs 互斥锁公平锁 vs 非公平锁可重入锁 vs 不可重入锁死锁死锁产生的必要条件如何简单的解决死锁问题 小结 这里不是描述的某个特定锁,而是描述的锁的特性,描述的是"一类锁". 乐观锁 vs 悲观…

人到中年三两事儿

人到中年&#xff0c;常常伴随着一系列的焦虑和烦恼。这些焦虑可能源自对工作的不确定性、对未来的担忧、对家庭责任的增加&#xff0c;或是对个人成就的反思。在这个年纪&#xff0c;我们可能会发现自己站在人生的十字路口&#xff0c;面临着重要的选择和决策。 首先&#xff…

数智时代的AI人才粮仓模型解读白皮书(2024版)

来源&#xff1a;极客邦 自 2023 年上半年起&#xff0c;ChatGPT 等大模型技术蓬勃发展&#xff0c;AI 技术不断突破边界&#xff0c;展现 出惊人的潜力和发展速度。从早期的逻辑推理、专家系统&#xff0c;到如今的深度学习、神经网络&#xff0c; AI 技术显著缩小了科学与实…

【面试经典 150 | 二分查找】搜索旋转排序数组

文章目录 写在前面Tag题目来源解题思路方法一&#xff1a;二分查找 写在最后 写在前面 本专栏专注于分析与讲解【面试经典150】算法&#xff0c;两到三天更新一篇文章&#xff0c;欢迎催更…… 专栏内容以分析题目为主&#xff0c;并附带一些对于本题涉及到的数据结构等内容进行…

Redis中的Lua脚本(二)

Lua脚本 创建排序辅助函数 为了防止带有副作用的函数令脚本产生不一致的数据&#xff0c;Redis对math库的math.random函数和math.randomseed函数进行了替换。对于Lua脚本来说&#xff0c;另一个可能产生不一致数据的地方是哪些带有不确定性质的命令&#xff0c;比如对于一个集…