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

news2024/11/15 23:25:41

引言

本文是对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.coloradmin.cn/o/1606009.html

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

相关文章

并发学习28--多线程 Fork、Join线程池

概念 使用 import java.util.concurrent.ForkJoinPool; import java.util.concurrent.RecursiveTask;public class TC51 {public static void main(String[] args) {//递归到最小不可分解单元&#xff0c;再进行计算ForkJoinPool pool new ForkJoinPool(5);pool.invoke(new My…

短视频素材在哪下载?优质视频素材APP下载

在这个视频内容日益成为关键传播手段的时代&#xff0c;选择正确的视频素材可以极大地增强你的内容影响力。无论是制作广告、社交媒体内容还是电影制作&#xff0c;高质量的视频素材都是不可或缺的。以下是精心挑选的全球顶级视频素材网站列表&#xff0c;每个网站都能为你的视…

嵌入式4-18

做一个简单数据库终端操作系统 #include <myhead.h> int main(int argc, const char *argv[]) {int id;char name[16];float score;sqlite3 *pNULL;if(sqlite3_open("./my.db",&p)!SQLITE_OK){printf("sqlite3_open error\n");return -1;} …

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

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

C语言进阶课程学习记录-函数指针的阅读

C语言进阶课程学习记录-函数指针的阅读 5个标识符含义解析技巧 本文学习自狄泰软件学院 唐佐林老师的 C语言进阶课程&#xff0c;图片全部来源于课程PPT&#xff0c;仅用于个人学习记录 5个标识符含义解析 int (*p1) (int* , int (*f) ( int* ) );定义了指针p1,指向函数&#…

面试题:一个 URL 在浏览器被输入到页面展现的过程中发生了什么

文章目录 前言一、回答二、深入追问 前言 这是一段~ 经典的旋律 ~&#xff0c;不好意思串台了&#xff0c;哈哈&#xff0c;这是一个经典的面试题&#xff1a;一个URL从浏览器到页面的过程中发生了什么&#xff0c;那么今天就带大家九浅一深来研究一下 觉得不错的同学可以加我…

RocketMQ 02 功能大纲介绍

RocketMQ 02 主流的MQ有很多&#xff0c;比如ActiveMQ、RabbitMQ、RocketMQ、Kafka、ZeroMQ等。 之前阿里巴巴也是使用ActiveMQ&#xff0c;随着业务发展&#xff0c;ActiveMQ IO 模块出现瓶颈&#xff0c;后来阿里巴巴 通过一系列优化但是还是不能很好的解决&#xff0c;之后…

SAP SD学习笔记06 - 受注的据否,受注的理由,简易变更(一括处理)

上文讲了一括处理和Block&#xff08;冻结&#xff09;处理。 SAP SD学习笔记05 - SD中的一括处理&#xff08;集中处理&#xff09;&#xff0c;出荷和请求的冻结&#xff08;替代实现承认功能&#xff09;-CSDN博客 本章继续讲SAP的流程中一些常用的操作。 1&#xff0c;受注…

计算机网络练习-计算机网络体系结构与参考模型

计算机网络分层结构 ----------------------------------------------------------------------------------------------------------------------------- 1.在ISO/OSI参考模型中&#xff0c;实现两个相邻结点间流量控制功能的是( )。 A.物理层 B. 数据链路层 C.网络层 D.传…

Nougat项目学习

简介 论文学习 https://arxiv.org/abs/2308.13418 项目地址 GitHub - facebookresearch/nougat: Implementation of Nougat Neural Optical Understanding for Academic Documents 项目主页 Nougat 这个项目主要是实现将pdf文档图片转换为markdown格式&#xff1b;针对纯英…

【蓝桥杯2025备赛】素数判断:从O(n^2)到O(n)学习之路

素数判断:从O( n 2 n^2 n2)到O(n)学习之路 背景:每一个初学计算机的人肯定避免不了碰到素数&#xff0c;素数是什么&#xff0c;怎么判断&#xff1f; 素数的概念不难理解:素数即质数&#xff0c;指的是在大于1的自然数中&#xff0c;除了1和它本身不再有其他因数的自然数。 …

宏集eX700M系列HMI实现港口设备数据上云

前言 随着港口设备信息化技术的快速发展&#xff0c;越来越多的企业想要把现场设备数据上传到云平台&#xff0c;进而实现关键数据的远程监控和分析处理。在此背景下&#xff0c;国内某信息化公司想要将港口设备数据通过MQTT上传到该公司自研IOT平台&#xff0c;实现数据上云&…

我三战华东师范大学的同桌真的很牛

标题党一下&#xff0c;其实是我的一个关系很好的高中同桌死磕华东师范大学三年&#xff0c;最终第二名上岸的故事。 其实我们是同一届的&#xff0c;我为了早点走选择了个排名还行的双非院校就走了&#xff0c;而我这个同桌相当有毅力&#xff0c;他能坚持这么久我其实很佩服&…

C++类和对象 中(六大默认成员函数)

前言 紧接着上一篇文章&#xff0c;接下来我们来认识下类的六大默认成员函数&#xff0c;如下图。之所以叫他默认成员函数&#xff0c;是因为即使我们不写&#xff0c;编译器会默认帮我们写&#xff0c;但只要我们自己显示的写了&#xff0c;编译器就不会帮我们生成对应的成员函…

基于小程序实现的精准扶贫数据收集系统

作者主页&#xff1a;Java码库 主营内容&#xff1a;SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app等设计与开发。 收藏点赞不迷路 关注作者有好处 文末获取源码 技术选型 【后端】&#xff1a;Java 【框架】&#xff1a;ssm 【…

Canal 同步mysql 到es 日期格式报错解决

第一步&#xff1a;下载源码alibaba/canal: 阿里巴巴 MySQL binlog 增量订阅&消费组件 (github.com) 第二步&#xff1a;编辑源码&#xff08;client-adapter下面的clinet-adapter.escore)&#xff1a; com.alibaba.otter.canal.client.adapter.es.core.support.ESSyncUt…

C++修炼之路之反向迭代器和非模板参数,模板特化,分离编译

目录 前言 一&#xff1a;反向迭代器 二&#xff1a;非类型模板参数 三&#xff1a;模板的特化 四&#xff1a;模板的分离编译 五&#xff1a;模板的优点与缺点 接下来的日子会顺顺利利&#xff0c;万事胜意&#xff0c;生活明朗-----------林辞忧 前言 在vector&am…

【网站项目】自习室预约系统

&#x1f64a;作者简介&#xff1a;拥有多年开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0c;帮助大学选题。赠送开题报告模板&#xff…

C#下Httpclient post请求获取令牌

1.postman测试ok 2.C#代码 public static async Task<string> testGetToken(string URL, string param){string responseBody "eee";//using (var clientHandler new HttpClientHandler()){ var handler new HttpClientHandler();handler.ServerCertificat…

如何在 VM 虚拟机中安装 OpenEuler 操作系统保姆级教程(附链接)

一、VMware Workstation 虚拟机 若没有安装虚拟机的可以参考下篇文章进行安装&#xff1a; 博客链接https://eclecticism.blog.csdn.net/article/details/135713915 二、OpenEuler 镜像 点击链接前往官网 官网 选择第一个即可 三、安装 OpenEuler 打开虚拟机安装 Ctrl …