【面试题】细说mysql中的各种锁
前言
作为一名IT从业人员,无论你是开发,测试还是运维,在面试的过程中,我们经常会被数据库,数据库中最经常被问到就是MySql。当面试官问MySql的时候经常会问道一个问题,”MySQL中有哪些锁?“当我们去网上找相应的资料的时候却是五花八门,张三说的一个样,李四说的另一个样。
like this…
案例一:
案例二:
案例三:
案例四:
搞得我们都不知道他们说到底对不对,全不全,…于是我们非常之困惑,面试的时候不知如何作答,正是为了解决这个问题,我查阅了很多书籍,国内外资料,写下这篇文章,希望对你有所帮助。
锁到底是个什么东西
维基百科是这样解释的:锁是一种保安设施,是人类为了保护自己的财产而发明的一种用钥匙才能开启的装置。就现代而言,是一种以钥匙、密码、电路或者其他用具来开启的封缄装置,用以防止物品被打开、移走兼具防护、管理甚至是装饰的作用。所以锁最重要的作用自然就是保护安全。
在计算机的世界里其实也一样,使用锁的目的几乎都是为了保证数据的安全可靠。在生活中锁千奇百怪,但我们可以将锁大致分为两种,一种是需要钥匙的,一种是不需要钥匙的,当然现代家庭中的指纹锁,数字密码锁都是需要钥匙的哈,只是钥匙不是实体钥匙而已。有很多朋友可能很纳闷,锁还有不需要钥匙的?答案是:有的
比如:
如果你来自农村,并且家里还有老宅那你可能也见过这样的锁:
这些锁都是不需要钥匙的,我们将之为”闩(shuan)锁“。
需要钥匙的锁就很常见了,比如:
再比如:
这种需要钥匙的锁我将之称为”锁“。
所以非常直观的感受就是虽然都为锁,但是闩锁比较”轻量“,自然也就没那么安全,而”锁“则麻烦一些,需要随身带着钥匙,所以相对也会更安全一些。相信到这里你已经对锁有比较好的理解了,那我们接着说数据库中的锁。
Mysql中的锁
在数据库中自然也将锁分成了两类,一类叫latch也就是闩锁,另一种叫lock(锁)。
latch一般称为闩锁(轻量级的锁),因为其要求锁定的时间必须非常短。若持续的时间长,则应用的性能会非常差。在InnoDB存储引擎中,latch又可以分为mutex(互斥量)和rwlock(读写锁)。其目的是用来保证并发线程操作临界资源的正确性,并且通常没有死锁检测的机制。
在数据库中,连接是一种珍贵的资源,连接自然不可能无限变多,也不可能同时被多个线程同时持有,这时候就需要用锁来保证同一时刻同一个连接只能被一个线程持有,这时候用到的锁就是我们说的闩锁。
而lock的对象是事务,用来锁定的是数据库中的对象,如表、页、行。并且一般lock的对象仅在事务commit或rollback后进行释放(不同事务隔离级别释放的时间可能不同)。此外,lock,正如在大多数数据库中一样,是有死锁机制的。所以我们在看一些文章的时候经常会看到将MySQL的锁分为行锁、表锁、页锁,他们得出的依据就是来来自于此。(关于行锁、表锁、页锁我们先按下不表,后面展开说!)
这里借用MySQL技术内幕中一张图,对比一下latch与lock的区别:
总结一下:其实他俩最大的区别就是作用的范围不同,latch更像是我们日常开发过程中使用到的应用程序级别的“普通锁”。而lock则是为了操作数据库中数据的一种特殊的“事务锁”,平时我们面试的时候面试官问的也主要是这种为了操作数据库中数据而存在的事务锁。
在这里先提前给大家总结一下:
站在更高的维度看问题-锁无非就是读和写
不知你是否发现,无论是生活中的各种鸟锁,无非就是要不要用到钥匙,
然后把他分成闩锁和锁。到了计算机界,锁无非也总的来说也就是两种,
一种是我拿到了锁我(一个事务)只让你(另一个事务)读只让你读,不让你写,另一种是:哥们我拿到锁了你们都往后靠一靠吧(连读都不让你读的),等我操作完了你们再来吧,好比厕所蹲坑,不可一个坑两个人同时蹲。所以你要明白“有空一起拉屎”只是调侃,可千万不能当真!
回归正题,于是乎按照严格我拿到锁了,你到底能不能读这个权限,将锁分为了两种:
- 共享锁(S Lock):也叫做读锁
- 排他锁(X Lock),也叫做写锁
注:你必须明白一点写的权限高于读,所以如果我说基于读这个权限,意思就是读都读不了,还写个毛啊!
所以我们总结再总结一下可以得出:
等等…我听说的全局锁、表锁、行锁你丫的没给我讲呢
前面我们已经讲了,锁无非就是读和写,这是从功能上来说,但是每个事务都有自己的表现形式呀,你说对吧?
在MySQL中,数据库中的数据被分为了"库–>表—>行",所以MySQL中的锁,按照锁的粒度分自然而然就产生对应的全局锁、表锁和行锁了哟!
- 全局锁:锁定数据库中的所有表
- 表级锁:每次操作锁住整张表
- 行级锁:每次操作锁住对应的行数据
好了有了上面的铺垫,我们继续讲解这三种锁的使用,以便你在工作和面试中“惊艳四座、大杀四方、godlike!”
全局锁就是对整个数据库实例加锁,加锁后整个实例就处于只读状态,后续的DML的写语句,DDL语句,已经更新操作的事务提交语句都将被阻塞。
“后续的DML的写语句,DDL语句,已经更新操作的事务提交语句都将被阻塞。” 这几句话列位能理解的吧?
好吧,你们都能理解,那我也当个小丑🤡讲一下吧:
DML的写语句:sql语句中的update和delete语句都是写语句
DDL语句:就是要修改表结构的语句,比如ALTER TABLE table_name ADD column_name data_type
已经更新操作的事务提交语句:这一句优点难理解,直接上代码:
BEGIN -- 第一句UPDATE `subject` SET `name`='ccc12' WHERE id =1 -- 第二句COMMIT;--第三句
他想表达的意思就是,在锁库之前已经执行了前面两句sql然后库被锁住了,这时候如果再执行第三句,那么这个操作就会被阻塞!!
证明:
首先我们先执行第一句:
再执行第二句:
好的,我们去另一个事务中把库锁了:
这时候我们再去第一个事务中执行提交语句:
哎呀,家人们呐,看到了没,他被阻塞住了,不执行了!
我们再把锁释放了:
我们再回到第一个事务:
COMMIT已经执行成功了,从花费时间上也不难看出确实是被阻塞了呢!
全局锁这么猛(锁的粒度太™的大了),他在什么地方使用呢?
全局锁典型的使用场景是做全库的逻辑备份,对所有的表进行锁定,从而获取一致性视图,保证数据的完整性。但是在数据库中加全局并不是一个好选择,因为数据库中加全局锁,是一个比较重的操作,存在以下问题:
-
1.如果在主库上备份,那么在备份期间都不能执行更新,业务基本上就得停摆。
-
2.如果在从库上备份,那么在备份期间从库不能执行主库同步过来的二进制日志(binlog),会导致主从延迟。
在lnnoDB引擎中,我们可以在备份时加上参数–single-transaction参数来完成不加锁的一致性数据备份。
mysqldump --single-transaction -uroot -p123456 test>test.sql
说完全局锁,我们接着说表锁,对,你没看错,是表锁,不是表嫂!
但是在这里我们要把它称为表级锁,而不是表锁,为什么要这么称呼呢?那肯定有是有道理滴,因为
同为表级锁,主要分为以下三类:
- 1.表锁
- 2.元数据锁(meta datalock,MDL)
- 3.意向锁
他们都可以称为表(级)锁,对于表级锁来说,每次操作锁住整张表,在MyISAM、InnoDB、BDB等存储引擎中都有实现。由于每次操作锁住整张表,所以表锁的锁定粒度大,发生锁冲突的概率最高,并发度低。
这下真的要开始讲表锁了!!
表锁主要分为两类:
- 1.表共享读锁(read lock)
- 2.表独占写锁(write lock)
共享读锁:当一张表被上了共享读锁以后,这张表只能被读不能被写,且读的话大家(不同的事务)都可以读,写的话大家都不能写。
举个例子好理解一点:
我们先将表上锁🔒:
BEGIN
LOCK TABLES `subject` READSELECT * FROM `subject` WHERE id=1COMMIT;
同一个事务内的读,如图:
第一步:
第二步:
不同的事务内的读:
同一事务内的写:
不同事务内的写:
独占写锁:当一张表被上了共享读锁以后,当前事务既能读数据也能写数据,同时还能修改表结构,别的事务既不能读数据也不能写数据,必须等到该锁被释放以后才能读写数据。(验证方式和上面一样,不再给图了)
这里一定要注意:我锁强调的是”别的事务“,而不是有些文章或者教学视频说的别的客户端!这是完全不同的概念,同一个客端可以上开启多个不同的事务!
总结如图:
表锁终于说完了,有些人看到这这里内容太多,估计已经暴躁了,想骂人!!
我也不想,可是它必须要讲!!
我们接着讲另一个表级锁–元数据锁
元数据锁(metadata lock) 也叫MDL,他的加锁过程是系统自动控制,无需显式使用,在访问一张表的时候会自动加上。MDL锁主要作用是维护表元数据的数据一致性,在表上有活动事务的时候,不可以对元数据进行写入操作。为了避免DML与DDL冲突,保证读写的正确性。在MySQL5.5中引I入了MDL,当对一张表进行增删改查的时候,加MDL读锁(共享);当对表结构进行变更操作的时候,加MDL写锁(排他)。
说白了,元数据锁其实就是”表结构锁“没人这么叫,你可以这么理解,意思就是数据增删改查的时候能动了表结构,不然就会产生冲突,比如你在插入数据的时候,你把我表结构的其中一列给删了,你这让我这么插?
好的,我们继续讲解最后一个表级锁–意向锁
意向锁,为了避免DML在执行时,加的行锁与表锁的冲突,在InnoDB中引入了意向锁,使得表锁不用检查每行数据是否加锁,使用意向锁来减少表锁的检查。
考虑这个例子:事务A锁住了表中的一行,让这一行只能读,不能写。之后,事务B申请整个表的写锁。如果事务B申请成功,那么理论上它就能修改表中的任意一行,这与A持有的行锁是冲突的。数据库需要避免这种冲突,就是说要让B的申请被阻塞,直到A释放了行锁。
数据库要怎么判断这个冲突呢?
step1:判断表是否已被其他事务用表锁锁表
step2:判断表中的每一行是否已被行锁锁住。
注意: step2这样的判断方法效率实在不高,因为需要遍历整个表。于是就有了意向锁。在意向锁存在的情况下,事务A必须先申请表的意向共享锁,成功后再申请一行的行锁。
在意向锁存在的情况下,上面的判断可以改成step1:不变,step2:发现表上有意向共享锁,说明表中有些行被共享行锁锁住了,因此,事务B申请表的写锁会被阻塞。
意向锁分为两类:
-
1.意向共享锁(IS):由语句select…lock in sharemode添加。与表锁共享锁(read)兼容,与表锁排它锁(write)互斥。
-
2.意向排他锁(Ix):由insert、update、delete、select…forupdate添加。与表锁共享锁(read)及排它锁(write)都互斥,意向锁之间不会互斥。
可以通过以下SQL,查看意向锁及行锁的加锁情况:select object_schema,object_name,index_name,lock_type,lock_mode,lock_data from performance_schema.data_locks;
终于到了”行级锁“——千呼万唤始出来
我们继续学习行级锁,行级锁每次操作锁住对应行的数据,锁定粒度最小,发生锁冲突的概率最低,并发度最高。 InnoDB存储引擎支持行级锁,InnoDB的数据是基于索引组织的,行锁是通过对索引上的索引项加锁来实现的,而不是对记录加的锁。(这一点非常重要)
对于行级锁,主要分为以下三类:
- **1.行锁(RecordLock):**锁定单个行记录的锁,防止其他事务对此行进行update和delete。在RC(读已提交)、RR(可重复读)隔离级别下都支持。
- **2.间隙锁(GapLock):**锁定索引记录间隙(不含该记录),确保索引记录间隙不变,防止其他事务在这个间隙进行insert,产生幻读。在RR隔离级别下都支持。
- **3.临键锁(Next-KeyLock):**行锁和间隙锁组合,同时锁住数据,并锁住数据前面的间隙Gap。在RR隔离级别下支持。
行锁也被叫做记录锁,InnoDB实现了以下两种类型的行锁:
1.共享锁(S): 允许一个事务去读一行,阻止其他事务获得相同数据集的排它锁。
2.排他锁(X): 允许获取排他锁的事务更新数据,阻止其他事务获得相同数据集的共享锁和排他锁。
其中insert、update、delete语句MySQL会自动为这些语句自动加上排他锁,select…lock in share mode语句会加上共享锁,select…for update加上排他锁,普通的select语句并不会加任何锁!
锁的升级与降级
默认情况下,InnoDB在REPEATABLE READ事务隔离级别运行,InnoDB使用next-key锁进行搜索和索引扫描,以防止幻读。
第一类情况:
- 针对唯一索引进行检索时,对已存在的记录进行等值匹配时,将会自动优化为行锁。
- InnoDB的行锁是针对于索引加的锁,不通过索引条件检索数据,那么InnoDB将对表中的所有记录加锁,此时就会升级为表锁。
第二类情况:
- 索引上的等值查询(唯一索引),给不存在的记录加锁时,优化为间隙锁。
- 索引上的等值查询(普通索引),向右遍历时最后一个值不满足查询需求时,next-key lock退化为间隙锁。
- 索引上的范围查询(唯一索引),会访问到不满足条件的第一个值为止。
注意: 间隙锁唯一目的是防止其他事务插入间隙。间隙锁可以共存,一个事务采用的间隙锁不会阻止另一个事务在同一间隙上采用间隙锁。
所以最后总结一下就是这样的:
最后
如果你能看到这里,那说明你真是太棒了,全文快五千字了,基本上把mysql的锁讲透了,同时你还有什么问题可以给我留言,一起进步!能一键三连的话,我将不甚感激!
相关文章:

【面试题】细说mysql中的各种锁
前言 作为一名IT从业人员,无论你是开发,测试还是运维,在面试的过程中,我们经常会被数据库,数据库中最经常被问到就是MySql。当面试官问MySql的时候经常会问道一个问题,”MySQL中有哪些锁?“当我…...

TMS320F280049 EPWM模块--TZ子模块(6)
下图是TZ子模块在epwm中的位置,可以看到TZ子模块接收内外部多种信号,经过处理后生成最终epwm波形,然后通过gpio向外发出。 TZ的动作有4个:拉高/拉低/高阻/不变。 TZ的内部框图见下图,可以看出: 1…...

数字乡村创新实践探索农业现代化路径:科技赋能农业产业升级、提升乡村治理效能与农民幸福感
随着信息技术的快速发展和数字化时代的到来,数字乡村建设正成为推动农业现代化、提升农业产业竞争力、优化乡村治理以及提高农民幸福感的重要途径。本文将围绕数字乡村创新实践,探讨其在农业现代化路径中的积极作用,以及如何通过科技赋能实现…...

linux中rpm包与deb包的区别及使用
文章目录 1. rpm与deb的区别2. deb软件包的格式和使用2.1 deb软件包命令遵行如下约定2.2 dpkg命令2.3 apt-命令 3. Unix和Linux的区别Reference 1. rpm与deb的区别 有的系统只支持使用rpm包安装,有的只支持deb包安装,混乱安装会导致系统问题。 关于rpm和…...

Linux中安装seata
Linux中安装seata 一、准备1、环境2、下载3、上传到服务器4、解压 二、配置1、备份配置文件2、导入sql3、修改配置前4、修改配置后5、在nacos中配置 三、使用1、启动2、关闭 一、准备 1、环境 因为要在 nacos 中配置,要求安装并启动 nacos 。可以参考这篇博客。 …...

预印本仓库ArXiv——防止论文录用前被别人剽窃
文章目录 一、什么是预印本二、什么是ArXiv2.1 ArXiv的领域2.2 如何使用 一、什么是预印本 预印本(Preprint)是指科研工作者的研究成果还未在正式出版物上发表,而出于和同行交流目的自愿先在学术会议上或通过互联网发布的科研论文、科技报告…...

LNMP 架构
1. 环境准备 环境准备 lnmp 需要 安装 nginx mysql php 软件 1.1 关闭防火墙 systemctl disable --now firewalld setenforce 0 1.2 安装依赖包 yum -y install pcre-devel zlib-devel gcc gcc-c make 1.3 创建运行用户、组 (Nginx 服务程序默认以 nobody 身份…...
谈谈Python中的单元测试和集成测试
谈谈Python中的单元测试和集成测试 Python中的单元测试和集成测试是软件开发过程中的重要环节,它们确保了代码的质量和稳定性。单元测试主要关注代码的最小可测试单元——通常是函数或类的方法,而集成测试则关注这些单元之间的协作和交互。下面…...
【2024】Prometheus通过node_exporter都监控了什么
我们通过prometheus进行监控,通过node_exporter进行Linux系统的监控。 那么我们通过node_exporter都监控了什么? 目录 常用指标CPU相关内存相关磁盘相关网络相关其他指标常用监控告警案例:cpu案例:内存案例:磁盘案例:网络案例:常用指标 Prometheus通过node_exporter可以…...

Centos7配置秘钥实现集群免密登录
设备:MacBook Pro、多台Centos7.4服务器(已开启sshd服务) 大体流程:本机生成秘钥,将秘钥上传至服务器即可实现免密登录 1、本地电脑生成秘钥: ssh-keygen -t rsa -C "邮箱地址 例:*****.163.com"一路回车…...

Android匿名共享内存(Ashmem)
在Android中我们熟知的IPC方式有Socket、文件、ContentProvider、Binder、共享内存。其中共享内存的效率最高,可以做到0拷贝,在跨进程进行大数据传输,日志收集等场景下非常有用。共享内存是Linux自带的一种IPC机制,Android直接使用…...

MySOL之旅--------MySQL数据库基础( 3 )
本篇碎碎念:要相信啊,胜利就在前方,要是因为一点小事就停滞不前,可能你也不适合获取胜利,成功的路上会伴有泥石,但是走到最后,你会发现身上的泥泞皆是荣耀的勋章! 今日份励志文案: 凡是发生皆有利于我 目录 查询(select) 1.全列查询 2.指定列查询 3.查询字段为表达式 编…...
阿药陪你学Java(第零讲)
第零讲:基本数据类型 Java包括两种数据类型,分别是内置数据类型(基本数据类型)和引用数据类型。 内置数据类型 Java提供了8中内置类型,其中包括4种数字整型、2种数字浮点型、1中字符型、1中布尔型。下面进行详细介绍…...

华院计算参编《金融业人工智能平台技术要求》标准
随着人工智能技术的迅猛发展,金融机构正在从业务场景化向企业智能化演进,金融业对智能化的需求愈加迫切。为引导产业有序发展、规范行业自律、加快金融行业智能化转型,中国信通院依托中国人工智能产业发展联盟(AIIA)及…...
vue3-element-admin二次开发遇到的问题总结,持续更新中
vue3-element-admin 是基于 Vue3 Vite5 TypeScript5 Element-Plus Pinia 等主流技术栈构建的免费开源的后台管理前端模板(配套后端源码)。 一、定制Element-Plus主题 1.创建 variables.scss 变量文件 /*variables.scss*/ /*覆盖element-plus变量*/…...

SpringMVC数据接收(全面/详细注释)
SpringMVC涉及组件: DispatcherServlet : SpringMVC提供,我们需要使用web.xml配置使其生效,它是整个流程处理的核心,所有请求都经过它的处理和分发![ CEO ]HandlerMapping : SpringMVC提供,我们需要进行…...

golang 冒泡、选择、插入、快速排序法
个人学习笔记~ 1. 冒泡排序 // Author sunwenbo // 2024/4/6 22:37 /* 1. 一共会经过arr.length -1 次的轮数比较,每一轮将会确认一个数的位置 2. 每一轮的比较次数逐渐的减少 [4,3,2,1] 3. 当发现前面的一个数比后面的一个数大的时候,就进行…...

vue3 +Taro 页面实现scroll-view 分页功能
需求 现在分页列表 后端只给你一个分页的数据列表 没有总页数 没有当前的分页 页数 只有这么一个list 、、、 如何去分页 我这使用的是scroll-view 组件 滑动到底部的事件 根据你当前设定的每页的数据数量和后端返回给你的数据列表数量 当某一次分页 两个数量不相等了以后 就…...
【http】常见http headers
相关文章:http 状态码 和http methods及restful api 常见http headers 1 常见的Request Headers Accept 浏览器可接收的数据格式 Accept-Encoding 浏览器可接收的压缩算法,gzip Accept-language 浏览器可接收的语言 Connection:keep-alive 一次TCP连接…...

Web App 入门指南:构建预测模型 App 的利器(shiny)
Web App 入门指南:构建预测模型 App 的利器 简介 近年来,随着机器学习和人工智能技术的快速发展,预测模型在各行各业得到了广泛应用。为了方便地部署和使用预测模型,将模型构建成 Web App 是一种非常好的选择。Web App 无需下载…...

以下是对华为 HarmonyOS NETX 5属性动画(ArkTS)文档的结构化整理,通过层级标题、表格和代码块提升可读性:
一、属性动画概述NETX 作用:实现组件通用属性的渐变过渡效果,提升用户体验。支持属性:width、height、backgroundColor、opacity、scale、rotate、translate等。注意事项: 布局类属性(如宽高)变化时&#…...

cf2117E
原题链接:https://codeforces.com/contest/2117/problem/E 题目背景: 给定两个数组a,b,可以执行多次以下操作:选择 i (1 < i < n - 1),并设置 或,也可以在执行上述操作前执行一次删除任意 和 。求…...
C++ 基础特性深度解析
目录 引言 一、命名空间(namespace) C 中的命名空间 与 C 语言的对比 二、缺省参数 C 中的缺省参数 与 C 语言的对比 三、引用(reference) C 中的引用 与 C 语言的对比 四、inline(内联函数…...

算法岗面试经验分享-大模型篇
文章目录 A 基础语言模型A.1 TransformerA.2 Bert B 大语言模型结构B.1 GPTB.2 LLamaB.3 ChatGLMB.4 Qwen C 大语言模型微调C.1 Fine-tuningC.2 Adapter-tuningC.3 Prefix-tuningC.4 P-tuningC.5 LoRA A 基础语言模型 A.1 Transformer (1)资源 论文&a…...

uniapp手机号一键登录保姆级教程(包含前端和后端)
目录 前置条件创建uniapp项目并关联uniClound云空间开启一键登录模块并开通一键登录服务编写云函数并上传部署获取手机号流程(第一种) 前端直接调用云函数获取手机号(第三种)后台调用云函数获取手机号 错误码常见问题 前置条件 手机安装有sim卡手机开启…...

如何应对敏捷转型中的团队阻力
应对敏捷转型中的团队阻力需要明确沟通敏捷转型目的、提升团队参与感、提供充分的培训与支持、逐步推进敏捷实践、建立清晰的奖励和反馈机制。其中,明确沟通敏捷转型目的尤为关键,团队成员只有清晰理解转型背后的原因和利益,才能降低对变化的…...
在树莓派上添加音频输入设备的几种方法
在树莓派上添加音频输入设备可以通过以下步骤完成,具体方法取决于设备类型(如USB麦克风、3.5mm接口麦克风或HDMI音频输入)。以下是详细指南: 1. 连接音频输入设备 USB麦克风/声卡:直接插入树莓派的USB接口。3.5mm麦克…...

macOS 终端智能代理检测
🧠 终端智能代理检测:自动判断是否需要设置代理访问 GitHub 在开发中,使用 GitHub 是非常常见的需求。但有时候我们会发现某些命令失败、插件无法更新,例如: fatal: unable to access https://github.com/ohmyzsh/oh…...
Yii2项目自动向GitLab上报Bug
Yii2 项目自动上报Bug 原理 yii2在程序报错时, 会执行指定action, 通过重写ErrorAction, 实现Bug自动提交至GitLab的issue 步骤 配置SiteController中的actions方法 public function actions(){return [error > [class > app\helpers\web\ErrorAction,],];}重写Error…...

Springboot 高校报修与互助平台小程序
一、前言 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,高校报修与互助平台小程序被用户普遍使用,为…...