【MySQL】如何理解MySQL的锁(图文并茂,一网打尽)
一、锁的介绍
锁是计算机协调多个进程或者线程并发访问某一资源的机制。那么如何保证数据并发访问的一致性、有效性是数据库必须解决的一个问题,锁的冲突也是影响数据库并发访问性能的一个重要因素,所以数据库中锁的应用极为重要,其复杂度也更高。
锁的分类,以锁的颗粒度为三类:
全局锁:锁定数据库中的所有表。
表级锁:每次操作锁住整张表。
行级锁:每次操作都锁到对应行的数据。
接下来就分别对这几种锁做一个解释。
二、全局锁
1、概念
对整个数据库实例加锁,加锁后整个实例就处于只读状态,对于后面的DML语句,DDL语句,已经更新操作的事务提交语句都会被阻塞。
典型的场景应用:数据备份。对所有的表进行锁定,从而获取数据的一致性,保证数据的完整性。
如图所示,我们加了全局锁之后,使用mysqldump取备份数据的时候,其他客户端的事务是不能执行DML操作、DDL操作的,但可以执行DQL操作,当我们备份好数据后,导出xxx.sql文件后,再解开锁,此时DML操作、DDL操作才生效。
(其中DML操作是指:对数据进行增加、删除、修改操作。DDL操作是指:主要是进行定义/改变表的结构、数据类型、表之间的链接等操作。DQL操作是指:对数据进行查询操作。还有DCL操作是指:主要是用来设置/更改数据库用户权限。)
2、语句
加锁:flush tables with read lock;
解锁:unlock table
3、不足
①:如果在主库上备份,那么备份期间都不能执行更新,业务基本上就停摆了 。
②:如果在从库上备份,那么在备份期间不能执行同步过来的二进制日志洗,会导致延迟。
二、表级锁
对于表级锁,锁定粒度答,发生锁冲突的概率 最高,并发度低。应用在MyISAM、InnoDB、BDB等存储引擎中。
表级锁分为表锁、元数据锁、意向锁三类。
1、表锁
(1)表共享读锁(read lock)
如图所示有两个客户端Client1、Client2当Client1执行加锁操作后,Client1、Client2都只能执行DQL操作不能执行DDL/DML操作(进行堵塞)。只有当Client1解锁后,才能恢复DDL/DML的操作。
(2)表独占写锁(write lock)
如图所示有两个客户端Client1、Client2当Client1执行加锁操作后,Client1对该表能读能写,Client2不能执行DQL操作和不能执行DDL/DML操作(进行堵塞)。只有当Client1解锁后,才能恢复Client2的DQL/DDL/DML的操作。
(3)语法
加锁:lock tables 表名 read/write。
释放锁:unlock tables / 客户端断开。
2、元数据锁(MDL)
元数据锁:加锁过程是系统自动控制的,无需显示使用,主要作用是为了维护表元数据的一致性。 在表中若有未提交的事务,不可以对元数据进行写入操作。 对表进行增删查改的时候加入MDL读锁(共享), 对表结构进行变更操作的时候加入MDL写锁(排他)。
MDL的读锁分为类型分为shared_read(执行select、select xxx lock in share mode 触发)、shared_write(执行insert、update、delete、select...for update 触发)。
①:读锁之间是兼容的
如图所示,两个客户端Client1、Client2,当这两个客户端执行CRUD操作的时候,系统就自动添加了MDL的读锁,而读锁之间是不排斥的,所以Client1与Client2对User表的操作不会造成堵塞。
②:读锁与写锁排斥、写锁与写锁排斥
如图所示,两个客户端Client1、Client2,假设Client1执行了DQL操作,那么此时系统产生了MDL读锁,如果这时我们的Client2执行DDL操作,就会被堵塞,因为DDL操作产生的是MDL的写锁,会与MDL的写锁排斥。此时只有Client1commit提交后,Client2的语句才会生效。
3、意向锁
为了避免DML在执行时,加的行锁与表锁的冲突,在InnoDB中引入了意向锁,使得表锁不用检查 每行数据是否加锁,使得意向锁来减少表锁的检查。
如图所示,当我们Client1执行一个update语句的时候,我们的mysql 会默认对更新的行加上行锁,
若此时没有意向锁,且Client2想对整张表进行锁表操作,那么Client2就会从第一条记录开始一条条查找对应行有没有行锁,找到行锁后在判断该行锁类型与添加的表锁是否冲突,再决定是否加锁,现实这个过程效率很低。
假如我们加了意向锁,如图所示,此时Client1执行上诉同样的操作,而Client2在执行使先 判断当前的意向锁 与表锁是否兼容:若兼容直接加锁,若不兼容则Client2的操作会阻塞,直到Client1进行了commit操作,且释放意向锁和行锁后,才生效。此时不用逐行检查行锁的情况,效率增加。
意向锁分为两类意向共享锁(IS)和意向排他锁(IX)两类,接下来做以下介绍。
(1)意向共享锁(IS)
意向共享锁,与表锁的表共享读锁(read)兼容,与表独占写锁(write)排斥。
语句:select ... (select语句)lock in share mode(触发)
如图所示,Client1先通过select ... (select语句)lock in share mode触发意向共享锁(IS),此时Client2执行锁表的read lock操作可以直接锁表,因为二者兼容,当 执行锁表的wirte lock此操作,则会被堵塞因为二者不兼容。
(2)意向排他锁(IX)
意向排他锁,与表共享读锁(write)、表独占写锁(read)都互斥。意向锁之间不会互斥。
语句:insert 、update、delete、select ... for update(触发)
如图所示,Client1通过insert 、update、delete、select ... for update语句 触发意向排它锁(IX),此时Client2执行表共享读锁(write)、表独占写锁(read)都会被互斥,因为不兼容,只有等Client1执行完毕提交后,Client2的指令才会触发。
三、行级锁
行级锁:是MySQL 中锁定粒度最小的一种锁,是针对索引字段加的锁,只针对当前操作的行记录进行加锁。 行级锁能大大减少数据库操作的冲突。其加锁粒度最小,并发度高,但加锁的开销也最大,加锁慢,会出现死锁。应用在Innodb储存引擎中。
行级锁分为行锁(Recode Lock)、间隙锁 (Gap lock)、临键锁 (Next-key Lock:行锁与间隙锁的组合)三类,接下来分别介绍。
1、行锁
行锁分为共享锁和排他锁两类。
(1)共享锁(s)
只允许一个事务去读一行,阻止其他事务获得相同的数据集的排它锁。(共享锁之间兼容,与排它锁之间排斥)
语句:select ... (select语句)lock in share mode 触发(select 不加锁)
(2)排他锁(x)
允许获取排它锁的事务更新数据,阻止其他事务获得相同数据集的共享锁和排他锁(排它锁与排它锁、共享锁之间都冲突)(阻止其他事务的读锁和写锁 )
语句:insert 、update、delete、select ... for update 触发
2、间隙锁
间隙锁唯一的目的就是防止其他事务插入间隙。造成幻读现象。
如图所示,Client1执行了一个update Student set age = 10 where id=5操作,此时因为表中没有id=5的字段,此时就会在id=7和id=3之间加一个间隙锁(不包含id=3和id=7的情况),此时,Client2又执行了一个insert Student values(6,'李蛋',6)指令,在id=3和id=7之间插入一条指令,因为加了间隙锁,所以插入操作会被阻塞,直到Client1完成commit提交后,Client2插入语句才会生效。
3、临键锁
临键锁,是记录锁与间隙锁的组合,它的封锁范围,既包含索引记录,又包含索引区间。默认情况下InnoDB在Repeatable Read事务隔离级别运行,InnoDB使用临键锁进行搜索和索引扫 描,以防止幻读。(临键锁与间隙锁相比,除了锁住当前记录也会锁定当前记录之前的一部分间隙)
四、再谈乐观锁与悲观锁
我们从mysql模式上分类来谈谈乐观锁与悲观锁这两种思想。
1、乐观锁
(1)概念
乐观锁是一种在数据库操作中用于处理并发问题的技术。它的思想是认为数据一般情况下不会造成冲突,所以在数据进行提交更新的时候,才会正式对数据的冲突与否进行检测,如果发现冲突了,则让返 回错误信息,让用户决定如何去做。
(2)实现
利用数据版本号(version)机制是乐观锁最常用的一种实现方式。一般通过为数据库表增加一个数字类型的 “version” 字段,当读取数据时,将version字段的值一同读出, 数据每更新一次,对此version值+1。当我们提交更新的时候,判断数据库表对应记录的当前版本信息与第一次取出来的version值进行比对,如果数据库表当前版本号与第 一次取出来的version值相等,则予以更新,否则认为是过期数据,返回更新失败。
(3)应用场景
①:低冲突环境。②:读多写少的场景。③ :短事务场景。④:互联网应用。⑤:分布式应用。
(4)缺点
①:冲突检测:在高并发的环境中,乐观锁可能会导致大量的冲突 。
②:处理开销:在处理冲突时,需要执行回滚和重试,这可能会增加系统的开销。
③:版本管理:乐观锁通常通过版本号(或时间戳)来检测冲突。这要求系统能正确的控制版本号,否则可能导致错误的版本冲突。
2、悲观锁
(1)概念
悲观锁是指数据在操作数据的时候比较悲观,每次去拿数据的时候认为别的线程也会同时修改数据,所以在每次拿数据的时候都会加锁,这样别的线程想要拿数据就会被阻塞直到它解开锁。
(2)实现
①:使用select...for update是MySQL提供的实现悲观锁的方式。
②:Java中使用synchronized和ReentrantLock等独占锁方式实现。
(3)应用场景
①:写操作比较多的场景。②:并发冲突高的场景。③:业务需要强一致性的的场景。
(4)缺点
①:需要实施阻塞,导致效率降低下。
②:可能造成某个线程永久等待,即发生死锁的可能性较大。
③:锁超时:如果一个事务长时间有锁而不被释放,可能导致其他等待锁的事务超时。
五、总结
这里博主整理我们常见的MySQL中锁的概念,还介绍了面试中 常问的关于乐观锁、悲观锁的 一些特点。相信一定对屏幕前正在阅读的小伙伴有所帮助,大家不要忘记点赞、关注,支持博主一波哦!后续还有更多内容与大家分享~
相关文章:

【MySQL】如何理解MySQL的锁(图文并茂,一网打尽)
一、锁的介绍 锁是计算机协调多个进程或者线程并发访问某一资源的机制。那么如何保证数据并发访问的一致性、有效性是数据库必须解决的一个问题,锁的冲突也是影响数据库并发访问性能的一个重要因素,所以数据库中锁的应用极为重要,其复杂度也更…...

【设计模式】01-装饰器模式Decorator
作用:在不修改对象外观和功能的情况下添加或者删除对象功能,即给一个对象动态附加职能 装饰器模式主要包含以下角色。 抽象构件(Component)角色:定义一个抽象接口以规范准备接收附加责任的对象。具体构件(…...

【Python笔记-设计模式】原型模式
一、说明 原型模式是一种创建型设计模式, 用于创建重复的对象,同时又能保证性能。 使一个原型实例指定了要创建的对象的种类,并且通过拷贝这个原型来创建新的对象。 (一) 解决问题 主要解决了对象的创建与复制过程中的性能问题。主要针对…...

启动node服务报错Error: listen EACCES: permission denied 0.0.0.0:5000
启动node服务报错: 解决方案: 将监听端口改成3000或者其他 修改后结果: 参考原文: Error: listen EACCES: permission denied_error when starting dev server: error: listen eacc-CSDN博客...

onlyoffice api开发
编写代码 按照https://api.onlyoffice.com/editors/basic编写代码 <html> <head><meta charset"UTF-8"><meta name"viewport"content"widthdevice-width, user-scalableno, initial-scale1.0, maximum-scale1.0, minimum-scal…...
设计模式-工厂方法模式(C++)
工厂方法模式(Factory Method Pattern)是一种创建型设计模式,它定义了一个用于创建对象的接口,但将实际的对象创建过程延迟到子类中。这种模式解耦了具体产品的创建过程,使得系统更加灵活和可扩展。 下面是一个使用 C…...

ThreeJS 几何体顶点position、法向量normal及uv坐标 | UV映射 - 法向量 - 包围盒
文章目录 几何体的顶点position、法向量normal及uv坐标UV映射UV坐标系UV坐标与顶点坐标设置UV坐标案例1:使用PlaneGeometry创建平面缓存几何体案例2:使用BufferGeometry创建平面缓存几何体 法向量 - 顶点法向量光照计算案例1:不设置顶点法向量…...

基于SpringBoot的家教管理系统
基于SpringBootVue的家教管理系统的设计与实现~ 开发语言:Java数据库:MySQL技术:SpringBootMyBatis工具:IDEA/Ecilpse、Navicat、Maven 系统展示 前台主页 家教 个人中心 管理员界面 摘要 本文介绍了基于SpringBoot框架开发的家…...

简单mock server模拟用户请求给小程序提供数据
整理小程序代码时发现一此小程序离开了mock-server基本上没有办法显示了,因此用node,express来满足给小程序提供演示数据的功能 const express require(express); const { createCanvas, Image } require(canvas); const fs require(fs); const path require(path);…...

【MATLAB】 EWT信号分解+FFT傅里叶频谱变换组合算法
有意向获取代码,请转文末观看代码获取方式~ 展示出图效果 1 EWT分解算法 EWT分解算法是一种基于小波变换的信号分解算法,它可以将信号分解为一系列具有不同频率特性的小波分量。该算法的基本思想是将信号分解为多个不同尺度的小波分量,并对…...
MATLAB中,如何捕获和处理异常?如何在MATLAB中自定义错误消息?在MATLAB中,error函数和warning函数有什么区别?
MATLAB中,如何捕获和处理异常? 在MATLAB中,捕获和处理异常通常使用try-catch语句。try块包含可能引发异常的代码,而catch块则包含当异常发生时执行的代码。以下是如何在MATLAB中捕获和处理异常的基本步骤: 使用try关键…...

【算法与数据结构】127、LeetCode单词接龙
文章目录 一、题目二、解法三、完整代码 所有的LeetCode题解索引,可以看这篇文章——【算法和数据结构】LeetCode题解。 一、题目 二、解法 思路分析:示例1为例,hit到达cog的路线不止一条,如何找到最短是关键。广度优先搜索是一圈…...

CAN——创建一个数据库DBC文件
一、创建一个工程 file——new——can 500kbaud1ch 得到一个工程文件.cfg 二、实现两个节点通讯 can networks 三、创建数据库DBC tool——candbeditor——file——creatdatabase——cantemplate.dbc 1.建数值表 view——value tables——空白处右击add—— definition 定…...

(十三)【Jmeter】线程(Threads(Users))之tearDown 线程组
简述 操作路径如下: 作用:在正式测试结束后执行清理操作,如关闭连接、释放资源等。配置:设置清理操作的采样器、执行顺序等参数。使用场景:确保在测试结束后应用程序恢复到正常状态,避免资源泄漏或对其他测试的影响。优点:提供清理操作,确保测试环境的整洁和可重复性…...

MySQL数据库基础(十三):关系型数据库三范式介绍
文章目录 关系型数据库三范式介绍 一、什么是三范式 二、数据冗余 三、范式的划分 四、一范式 五、二范式 六、三范式 七、总结 关系型数据库三范式介绍 一、什么是三范式 设计关系数据库时,遵从不同的规范要求,设计出合理的关系型数据库&…...
掌控互联网脉络:深入解析边界网关协议(BGP)的力量与挑战
BGP简介 边界网关协议(Border Gateway Protocol,BGP)是互联网上最重要的路由协议之一,负责在不同自治系统(AS)之间传播路由信息。BGP使得互联网中的不同网络可以互相通信,支持互联网的规模化扩…...

Vue2页面转化为Vue3
vue2element-ui转化为Vue3element plus 后台管理系统:增删查改 vue2页面: <template><div class"app-container"><div><el-form:model"queryParams"ref"queryForm"size"small":inline&qu…...
【课程作业】提取图中苹果的面积、周长和最小外接矩形的python、matlab和c++代码
提取图中苹果的面积、周长和最小外接矩形 在图像处理中,提取对象的关键属性是常见的任务之一。本文将演示如何使用三种流行的编程语言——Python、Matlab和C,利用相应的图像处理库(OpenCV或Matlab内置函数)来提取图像中苹果的面积…...

解决easyExcel模板填充时转义字符\{xxx\}失效
正常我们在使用easyExcel进行模板填充时,定义的变量会填充好对应的实际数据,未定义的变量会被清空,但是如果这个未定义的变量其实是模板的一部分,那么清空了就出错了。 在这张图里,上面的是模板填充后导出的文件&…...

在项目中使用CancelToken选择性取消Axios请求
Axios 提供了 CancelToken 类来创建取消标记。取消标记实际上是一个包含 token 标记和 cancel 方法的对象。 1、基本使用方法 const CancelToken axios.CancelToken; const source CancelToken.source();axios.get(/user/12345, {cancelToken: source.token }).catch(functi…...
Vim 调用外部命令学习笔记
Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...
[2025CVPR]DeepVideo-R1:基于难度感知回归GRPO的视频强化微调框架详解
突破视频大语言模型推理瓶颈,在多个视频基准上实现SOTA性能 一、核心问题与创新亮点 1.1 GRPO在视频任务中的两大挑战 安全措施依赖问题 GRPO使用min和clip函数限制策略更新幅度,导致: 梯度抑制:当新旧策略差异过大时梯度消失收敛困难:策略无法充分优化# 传统GRPO的梯…...
【根据当天日期输出明天的日期(需对闰年做判定)。】2022-5-15
缘由根据当天日期输出明天的日期(需对闰年做判定)。日期类型结构体如下: struct data{ int year; int month; int day;};-编程语言-CSDN问答 struct mdata{ int year; int month; int day; }mdata; int 天数(int year, int month) {switch (month){case 1: case 3:…...

Linux 文件类型,目录与路径,文件与目录管理
文件类型 后面的字符表示文件类型标志 普通文件:-(纯文本文件,二进制文件,数据格式文件) 如文本文件、图片、程序文件等。 目录文件:d(directory) 用来存放其他文件或子目录。 设备…...

CMake基础:构建流程详解
目录 1.CMake构建过程的基本流程 2.CMake构建的具体步骤 2.1.创建构建目录 2.2.使用 CMake 生成构建文件 2.3.编译和构建 2.4.清理构建文件 2.5.重新配置和构建 3.跨平台构建示例 4.工具链与交叉编译 5.CMake构建后的项目结构解析 5.1.CMake构建后的目录结构 5.2.构…...
FastAPI 教程:从入门到实践
FastAPI 是一个现代、快速(高性能)的 Web 框架,用于构建 API,支持 Python 3.6。它基于标准 Python 类型提示,易于学习且功能强大。以下是一个完整的 FastAPI 入门教程,涵盖从环境搭建到创建并运行一个简单的…...

UDP(Echoserver)
网络命令 Ping 命令 检测网络是否连通 使用方法: ping -c 次数 网址ping -c 3 www.baidu.comnetstat 命令 netstat 是一个用来查看网络状态的重要工具. 语法:netstat [选项] 功能:查看网络状态 常用选项: n 拒绝显示别名&#…...
AI编程--插件对比分析:CodeRider、GitHub Copilot及其他
AI编程插件对比分析:CodeRider、GitHub Copilot及其他 随着人工智能技术的快速发展,AI编程插件已成为提升开发者生产力的重要工具。CodeRider和GitHub Copilot作为市场上的领先者,分别以其独特的特性和生态系统吸引了大量开发者。本文将从功…...

中医有效性探讨
文章目录 西医是如何发展到以生物化学为药理基础的现代医学?传统医学奠基期(远古 - 17 世纪)近代医学转型期(17 世纪 - 19 世纪末)现代医学成熟期(20世纪至今) 中医的源远流长和一脉相承远古至…...
MySQL 8.0 事务全面讲解
以下是一个结合两次回答的 MySQL 8.0 事务全面讲解,涵盖了事务的核心概念、操作示例、失败回滚、隔离级别、事务性 DDL 和 XA 事务等内容,并修正了查看隔离级别的命令。 MySQL 8.0 事务全面讲解 一、事务的核心概念(ACID) 事务是…...