MySQL隔离级别的底层理解(MVCC+锁)

news2025/2/23 18:21:12

MySQL事务的隔离级别和并发的关系

  • mysql是一个C/S架构的软件, 也就意味着, 同一个mysql服务器可能同时存在很多的clients集合来访问. 此时最重要的是什么?   并发性. 并发时候的安全. 
  • 并发和数据库安全性本来就是相互矛盾的。要保证更好的安全性最好的方式是什么? 完全舍弃并发. 同时只允许一个用户访问mysql, 串行化. 但是显然这是不现实的事情. 所以权衡两者,出现了不同的隔离级别. 隔离级别越高, 安全性越高, 并发度自然就越低.

至此,自然就知晓了不同的隔离级别出现的原因了.

四种隔离级别:

read uncommited: 读未提交. 事务还没有提交, 别人就可以看见。 存在脏读,不可重复读, 幻读现象, 完全没有任何安全性, 隔离性最低, 相应并发度最高,but 几乎不用, 实在是不安全.

read commited: 读已提交. 事务提交,别人才能看见, 与上述相比解决了脏读的现象. 安全性有所提升. 也是现在数据库比较常见的隔离级别之一

repeatable read: 可重复读, 相较于上述,通过每次读取第一版历史快照的方式实现重复读前后数据一致性. 解决了不可重复复读的问题. 

serializable: 串行化, 通过加锁的方式来保证了绝对的安全, 不存在任何的安全性问题, 同时也解决了幻读的问题, 针对幻读的解决用到了间隙锁,详见后文阐述。加锁导致了并发度很低. 并发度是最低下的.

查看隔离级别和事务提交:

  • select @@tx_isolation;      查看事务隔离级别
  • select @@autocommit;      查看是否自动提交事务 

MVCC支持的隔离级别

MVCC快照读取是一种非锁定读. 多版本并发读取.

适用于读已提交和可重复读的底层.      

不加锁的不用wait阻塞的并发读取. MVCC是一种并发控制技术

select每一次都是读取的快照数据

update,insert, delete, lock操作读取都叫做当前数据. (后序细说.

实现核心:快照数据, 快照数据就像是照片一样. 每一次读取快照数据,而不是实际的表中数据,然后快照数据按照不同的隔离级别要求规则来跟新。来实现不加锁的一种读取方式.

快照数据来源: 多版本数据链条.   依照不同隔离级别读取不同版本的数据来实现。

首先是已提交隔离级别(RC):

  • 每一次select都重新生成快照数据.
  • 竟然是每一次select都从新生成快照数据. 那快照数据就是最新版本的快照数据, 所谓快照数据就像是卡擦一下拍的一张照片.
  • 快照数据的跟新时期:  存在commit的时候, 或者事务本身自己进行update更新操作.

注意, RC隔离级别下存在不可重复读原因就是上述的每一次select都重新生成快照数据.竟然每一次select都重新拍摄一张快照, 快照自然就是最新版本的。别的事务完成的commit操作自然也会被读取到. 自然在其他事务commit前后的数据读取结果不会一致,也就实现了可重复读取操作了撒.

怎么读取的: 其实就是在版本链的最初版本卡擦一下拍了一张照片而已:

 快照: 也叫做read view: 读视图。肉眼所见不一定为真。所以还是存在幻读嘛

再强调RC核心. 每一次select均重新重新重新重新产生快照数据.

并且每一次commit均会跟新版本数据链. 每一次commit均跟新版本数据链条。

(实现了read commited, commit了就跟新版本数据链条 

  快照数据依据版本数据链条的头部最新数据产生. 卡擦,照最新的)

每一次的select 均从新产生快照数据,自然会出现其他事务commit前后两版截然不同的快照数据,这就是不可重复读取. 

可重复读隔离级别(RR):

好嘛好嘛,既然每一次select都产生快照数据会造成,其他commit前后select结果是截然不同的两张快照数据。      --------》   在本事务中. 我仅第一次commit操作才产生固定的快照数据. 后序每一次select 都直接拿取第一次select的快照数据就OK了塞.    (重复读取操作也不会造成read view 的差异了. )

当然:快照数据还有一个原则,当前事务自己的跟新操作可以照上. 

验证一下RC是不是每一次select操作均产生快照数据以及RR仅第一次select产生快照数据

(不然口说无凭):

RC隔离级别之下的结果

事务1: 先进行update 王妈年龄 = 50操作.  and commit;    

事务2: 在事务1 完成上述操作之前进行select. 和完成操作之前 select。 按照上述快照数据产生的原则是看当前commit的最新数据和本事务更改的数据,自然结果不一致   

RR 隔离级别下的结果. 不演示大家也晓得,竟然是可重复读取操作, 前后select结果必然一致,这个一致,依赖的就是快照数据产生的时机不同。RR仅第一次select产生快照数据,后序select直接读取第一版select的快照数据即可.   (自然重复读取前后保持是一致的)

当前读(Current Read)什么时候是当前读取?  

读取的是记录的最新版本,并且当前读返回的记录。如insert,delete,update,select...lock in share mode/for update

上述这些操作. 说白了都不是基于read view的结果进行的. 而是基于内存中实实在在的存储的数据是什么就是什么。而不是依照快照数据来完成上述操作。都是依照数据库的实实在在的当前最新数据完成上述操作. 

其实undo log也依赖于版本控制。或者说数据版本链条。undo log 依赖的就是一个roll指针,回滚指针, 回滚到之前的版本. 出错回滚操作. 

DB_TRX_ID:事务ID DB_ROLL_PTR:回滚指针

锁支持的隔离级别

锁类型:

表锁&行锁

表级锁:   锁的粒度大, 锁住整张表, 并发度最低

行级锁:   锁的粒度小, 锁住一行, 并发度相较于表锁更高

共享锁与排他锁

shared mutex: S锁,共享锁. 也叫做读锁, 允许多个client 同时获取一把读锁. 可以读 + 读锁不冲突

Exclusive mutex :X锁, 排他锁, 写锁,独占锁。很是霸道. 不允许和仍何锁共存. 一旦加了写锁,便不可以再加写锁甚至读锁.

加锁方式:   select ... lock in share mode; 加读锁    select ... for update; 加写锁.  

Innodb 支持行锁 + 间隙锁(gap lock)解决幻读问题

  • innodb 存储引擎支持行级锁, 拥有更高的并发能力
  • MyISAM 存储引擎支持表锁, 并发量相对低于innodb存储引擎
  • 注意: innodb的行锁是加在索引列上的.而不是给表的行记录加锁实现的. (用于索引项,否则还是表级锁)
  • 索引可能失效, 如果直接整个全表扫描效率还高于使用索引, innodb会采取全表扫描, 加表锁,而非使用行锁.

record lock 记录锁. 锁住某行记录. 锁住索引项对应的所有记录.

gap lock: 间隙锁. 用于锁住记录与记录之间的间隙. 避免间隙插入操作造成的幻读现象. 

Next-key lock = record lock + gap lock.

案例测试:

目前,存在一张student 表结构数据如下:

 首先我先测试一下是表锁还是行锁:

先对where id = 2 加读锁. 再另起一个事务尝试对此列加写锁,肯定是失败的,写锁不与其他锁共存。    当然再另起一个事务加读锁是可以的,因为读锁与读锁是可以共享的.   验证家的是行锁,不是表锁,对其他列加写锁是OK的。

注意,对索引列才能加锁.

 上述实验初步验证了两个点:

  • 首先innodb是对索引列支持加行锁的. 性能更高,锁粒度小
  • 另外读锁(共享锁) 可以多事务同时共享,不冲突。 写锁(排他锁) 叼的很,不与任何锁共事。

场景2: 验证串行化隔离级别的场景下所有操作自动加锁. (串行化底层实现, 加锁)

首先第一步修改隔离级别为: serializable

接下来,我们尝试做一些读取和写操作,看看是否存在等锁的现象.

 首先读取一下id = 3这行记录,再另外一个事务尝试为这条记录的name 修改为丑八怪.

 很是明显,和我们刚刚上述加写锁的现象一毛一样,被阻塞住了,其实也就是暂时获取不了写锁.

至此,可以简单的证明串行化的底层就是加锁. 对读写操作加上对应的读写锁.

接下来, 尝试给区间加锁。看一看间隙锁是如何加的. 同时对于幻读现象的解决做理解。首先先看一个幻读的现象.   当然串行化下是不会发生的。因为加了间隙锁。为了可以看到幻读现象。我就直接画图简单说明一下幻读现象.

 我们尝试一下在串行化隔离级别场景下是否存在如此现象.

啥情况,根本就不让插入. 其实就是对麻花索引枷锁了。而且加的并不是record lock. 而是key-next lock = record lock + gap lock;

(麻花-1, 麻花] (麻花, +oo)  全部给锁住了.

间隙锁,会将索引左右的间隙加锁。gap lock , 也就是将左右记录中间部分也给锁住,如果没有左右记录就直接索住到无穷. 锁住间隙就是为了避免从间隙中插入。造成了幻读现象。有了间隙锁,别的事务在插入的时候会被阻塞。自然也就避免了因为跟新记录而出现的幻读的现象了

串行化隔离级别解决幻读的方式就是通过自动加上间隙锁的方式来避免, 其他事务在刚刚查询的位置及其之后再进行插入并且提交. 从而引发的刚刚的查询结果失效(结果跟新了)。仿佛刚刚的查询结果是虚幻的幻读现象.  解决办法就是加上间隙锁。使得无法在对应查询位置(区间)进行插入造成之前的查询结果虚幻.

测试测试罗: 用另外一个事务对我们的间隙做出插入,看看是否可以完成插入操作

(id, name, age):   先插入一个(10, "王婆", 25); 插入不进来,被(21, 30)之间的gap lock 锁住的.

 

再插入 (10, "王婆", 20) 还是插入不进来, 在(20, 21) gap 间隙中, 也被锁住了.

 But 神奇来了. 插入(4, "王婆", 20) OK了,可以插入,因为他并不在(20, 21) 之间. 而是在(20, 20) 之间.    why?   辅助索引相等按照主键主键主键递增插入间隙.  当然前提没有间隙锁. 

意向锁

  • 意向锁是为了更快的检测行级锁的存在,以便于判断是否能加表锁而出现的.

简单的举一个栗子, 比如所一张表中存储一万行数据, 现在我们需要为其加表级排他锁, 此时我们需要检测的是表中是否加了行锁. 怎么检测行锁. 是遍历每一行去判断吗? 效率过于低下了,

于是出现了意向锁. 意向锁相当于是一种表级锁.  

每一次获取锁的时候首先都会先获取意向锁. 意向锁和行锁是可以共存的.      

意向锁是mysql内存自己加上的, 要获取行锁就会自动先获取表的意向锁.

这样真的加表锁的时候,看到了存在对应地 意向锁, 就知道这个表存在某一行加上了锁,所以就不能再加排他锁了。

 意向锁,就是为了做行级锁和表级锁之间地一个桥梁地存在. 否则在加表级锁地时候如何感知一张表是否已经存在行级锁,难道要一行一行地轮询吗?数据量大的情况下效率过于低下.

死锁简单理解

  • 对于表一般不太会死锁。因为锁粒度大. 交叉获取锁冲突发生的可能性小. 但是对于Mysql的Innodb存储引擎因为存在索引,而且支持行级锁。并发度高,锁粒度小,所以更容易出现锁的冲突,死锁现象.

 Mysql解决办法, 测试一下看看就晓得了

 Mysql要是存在这种交叉相互获取对方事务持有的锁情况下会自动检测到死锁报错

undo log 和 redo log 日志的简单理解

  • 在上述, 基本算是简单的介绍完了RC, RR, 串行化隔离级别的底层实现. RC和RR 依赖于MVCC非锁定读读取快照数据的方式实现了  读取commit数据, 和仅第一次select生成快照数据来实现的可重复读
  • 也介绍了串行化的底层实现是加锁. 加记录锁, 间隙锁, 意向锁. 自动加.

undo log (逻辑日志/回滚日志)和 redo log (重做日志) 都是物理日志.   当然,日志在内存中存在缓冲区,专门用于临时记录日志内存,肯定存在缓冲区不能说每一次日志操作都直接进行磁盘IO,肯定是在一定的实际将缓冲区中的日志内存落盘刷新到磁盘上面去的.

如果宕机了,断电了,再次启动数据库,内存上的数据如何恢复。打开redo log 物理日志, 将redo log 物理日志上面的操作进行从做, 还原断电前的内存内容.

Mysql 日志 》 MySQL数据.  数据没了可通过日志恢复. 一次登录的数据是临时的. 下一次可以通过日志恢复. 日志才是MySQL持久化的关键.  

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

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

相关文章

云原生系列 四【轻松入门容器基础操作】

✅作者简介: CSDN内容合伙人,全栈领域新星创作者,阿里云专家博主,华为云云 享专家博主,掘金后端评审团成员 💕前言: 最近云原生领域热火朝天,那么云原生是什么?何为云原生…

最详细的Keycloak教程:Keycloak实现手机号、验证码登陆——(一)Keycloak的下载与使用

目录一、 简介二、Keycloak下载与启动三、配置国际化内容一、 简介 接触keycloak已经半个多月了,主要是为了用来集成现已有的项目,也是弄得头大,代码不负脱发人,也是有点小成果了,在这里把自己的这点小小经验分享给大…

CMOS IC功耗类型及其影响因素

目录 概述 开关功耗(Switch Power) 内部功耗(Internal Power) 漏电功耗(Leakage Power) 工艺库相关 开关功率相关信息 内部功耗相关信息 漏电功耗相关信息 例子 概述 该部分对IC功耗的类型进行介绍 先总体来…

安装黑苹果常见问题总结

黑苹果字体模糊? 由于macOS使用了HiDPi技术以达到更高的每英寸像素率,即缩放,因此普通显示器只要不是4k分辨率,安装黑苹果后一定会遇到字体模糊的问题,解决方法可以阅读我往期发布的文章。 为什么用iStat Menus无法检…

期末前端web大作业:用DIV+CSS技术设计的动漫网站——火影忍者6页 带报告

⛵ 源码获取 文末联系 ✈ Web前端开发技术 描述 网页设计题材,DIVCSS 布局制作,HTMLCSS网页设计期末课程大作业 | 网页设计作业 | 动漫网页设计 | 动漫网页设计成品 | 动漫网页设计成品模板 | 简单漫画网页设计成品 | HTML期末大学生网页设计作业 HTML:结…

深度学习第四课——卷积神经网络(week 1)

目录 一、前言 1.1 卷积 1.2 其他滤波器 1.3 Padding 1.3.1 解释 1.3.2 填充多少像素的选择 1.4 卷积步长 1.5 三维卷积 1.6 单层卷积网络 1.7 深度卷积神经网络的一个示例 1.8 池化层 1.8.1 最大池化 1.8.2 平均池化 1.8.3 总结 1.9 卷积神经网络示例 1.10 为…

23种设计模式

1.创建型模式 ① 创建型模式的作用就是创建对象,说到创建一个对象,最熟悉的就是 new 一个对象,然后 set 相关属性 ② 但是很多场景下,需要给客户端提供更加友好的创建对象的方式,尤其是那种我们定义了类,但…

leetcode:644. 子数组最大平均数 II【浮点数二分 + 子数组最大平均值技巧】

目录题目截图题目分析ac code总结题目截图 题目分析 枚举铁超时, 10 ** -5考虑二分平均值需要同时考虑总和和长度能否只考虑一个考虑每个数num’ num - avg这样可以忽略长度猜一个guess_avg是否可能达到num’ -> num - avg_guess区间sum(num’) > 0说明其真…

Linux 开机运行sh 脚本 三种方法

一、修改开机启动文件​​​​​​​ /etc/rc.local(或者/etc/rc.d/rc.local) 1、编辑rc.local文件(命令后面让得加&号,表示后台运行) 2、最后修改rc.local文件的执行权限: chmod x /etc/rc.local二…

实践历练的力量

要让你的屁股和椅子建立起深刻的友谊来,要坚持下来。 掌握知识离不开实践和做,只有经历了这样的过程才能将知识转换为自己的。也才能真正明白在什么环境下需要什么样的知识。 解决问题。 真正的学习一定包括实践,而实践是更重要的学习。学…

【sfu】接收侧拼装H264 帧后的回调流程

sfu 基于webrtc协议栈,【sfu】rtc 入口 预先分配了资源,并创建了adpter模块和call模块。【webrtc】rtp包组帧 :涉及到收到rtp包到组帧、传递给Frame处理直到解码器的流程。帧就是从解码器导出的。我们只需要注册1个外部解码器就可以拿到编码后的H264 帧,给到其他流程处理。接…

【JVS低代码开发平台】支持纯手工配置的数据加工、处理、展现的数据仓库

数据智仓英文名称为Smart Data Warehouse,可简写为SDW。数据智仓是JVS整体企业数字化解决方案的核心能力,与JVS的低代码开发套件平级,如下图所示: 数据仓库的目的是构建面向分析的集成化数据环境,为企业提供基于数据的…

SOLIDWORKS 2023新功能揭秘!升级版轻松找到材料明细表修改

SOLIDWORKS 2023版本已经与大家见面,今天众联亿诚继续和大家分享SOLIDWORKS 2023 工程图的亮点新功能之一:材料明细表的覆盖。 材料明细表的覆盖 SOLIDWORKS工程图是我们常用的功能之一。当采用断开链接模式修改材料明细表的内容时,修改的内容…

【强化学习论文合集】AAAI-2022 强化学习论文 | 2022年合集(二)

强化学习(Reinforcement Learning, RL),又称再励学习、评价学习或增强学习,是机器学习的范式和方法论之一,用于描述和解决智能体(agent)在与环境的交互过程中通过学习策略以达成回报最大化或实现特定目标的问题。 本专栏整理了近几年国际顶级会议中,涉及强化学习(Rein…

【web前端期末大作业】HTML+CSS宠物狗静态网页设计

🎉精彩专栏推荐 💭文末获取联系 ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 💂 作者主页: 【主页——🚀获取更多优质源码】 🎓 web前端期末大作业: 【📚毕设项目精品实战案例 (10…

2.18 小红书的表情文案一键生成,原来这么简单【玩赚小红书】

想知道小红书的表情文案是怎么生成的,比如这种: 情人节走心 高调仪式感浪漫小 机! 式秀恩爱,不如比比谁更走心!❤️ EVERYDAY7️⃣彩⭐期裤 高浓度释放爱意讯号~ 今年情 节,大胆直接的爱意让他抱个 怀&…

【爬虫】Python爬取世界杯球员榜单并保存到excel经验分享

大家好 我是Yhen 今天给大家分享一下 如何爬取卡塔尔世界杯球员榜 数据来源:百度体育 https://tiyu.baidu.com/match/%E4%B8%96%E7%95%8C%E6%9D%AF/tab/%E7%90%83%E5%91%98%E6%A6%9C/current/0 文章目录一.需求分析二.思路分析三.代码实战四.源码获取一.需求分析…

XSS game -xss学习

网址 https://xss-game.appspot.com/level1Level 1: Hello, world of XSS payload: <script> alert(1); </script>漏洞产生处: message "Sorry, no results were found for <b>" query "</b>."Level 2: Persistence is key…

基于 urlimport 进行瘦身,提升编译效率

1. 基于 urlimport 进行瘦身&#xff0c;提升编译效率urlImport 是 NextJS 提供的一个实验特性&#xff0c;支持加载远程 esmodule NextJS 会在本地对所加载的远程模块进行缓存&#xff0c;减少了我们所需构建的模块数&#xff0c;缺点是它会影响 treeShaking 的一个效果&…

【强化学习论文合集】ICLR-2022 强化学习论文 | 2022年合集(四)

强化学习(Reinforcement Learning, RL),又称再励学习、评价学习或增强学习,是机器学习的范式和方法论之一,用于描述和解决智能体(agent)在与环境的交互过程中通过学习策略以达成回报最大化或实现特定目标的问题。 本专栏整理了近几年国际顶级会议中,涉及强化学习(Rein…