当前位置: 首页 > news >正文

MySQL—隔离级别和MVCC

前言

还是像我剖析线程池的时候所说,我感觉我确实走的太快了,不过学的早的好处就是可以随时调整,那不如我们现在朝花夕拾一下,后面几个博客估计也都是MySQL

正文

并发问题

隔离级别是因为并发问题而生的,那到底MySQL会有哪些并发问题

误区

  • 这里大家可能会进入一个误区,我发现别人更新的数据不是很正常吗,我就是在获取最新的这个数据
    但是大家要注意,这里是一个事务,事务具有隔离性(这里破坏的就是隔离性),从表现上来看。这里我一个事务具有原子性,两次操作查询的目标应当一致,所以不可重复读和幻读我觉得也是破坏原子性的一个体现(这个不是标准,只是帮助理解,这个话不要记,因为这里本身在一个线程里面这里的两个操作看起来就是无缝执行的,所以其实符合原子性

脏读

这个就是🈯️线程A正在修改这个SQL数据,这个时候事务没有提交,这个时候线程B来查询这个数据,但是这个时候获取到了线程A还未修改的数据

不可重复读

这个指的就是线程A有两次查询操作,第一次查询比如是100,但是中途线程B来修改数据,把这里的100修改成了1000,然后A第二次执行查询操作,发现这里是1000,同一个事务里面两次读取不一致

幻读

  1. SQL经典定义
    这个指的就是比如我线程A还是查询两次,第一次查询当前有5行数据,线程B再插入一条(对空白线程A 不操作的地方做操作),第二次线程A查询发现有6条数据,就像出现了幻觉,这个就叫幻读
  2. MySQL RR级别 InnoDB独有现象
    这里指的就是比如我线程A读一下我这个数据里面只有1 3 5,然后线程B插入一个4,然后我这个A的第二个操作恰好也是插入一个4,发现冲突,线程A再读,发现只有1 3 5没有4。这个就像幻觉一样,这个也是幻读

隔离级别

这里企业大多使用RC或者RR,大部分都是RC,因为这里越往下,并发性能也就越差,特别是这里的串行化,堪比单线程的
想看这里的实现原理,这里必须得看看下面的MVCC

  1. 读未提交(read uncommited):意思就是如果这个时候你没有提交,我也可以看到你的数据
  2. 读已提交(read committed RC):这里的意思就是我只能看到你提交后的数据**(这里的实现是引入了快照读)**
  3. 可重复读(repeatable read RR):意思就是这里你开始我看到你什么样,执行过程中也看你什么样**(这里的解决方案是一个事务只有一个快照)**
  4. 串行化(serializable):这个就是多个事务之间发生读写冲突的时候,得排队,一个事务一个事务来(堪比单线程)

这个就是不同级别可能出现的问题,但是MySQL的RR可以很大程度避免幻读,但是无法完全避免幻读

MVCC

这个东西就是数据库来实现上面四种隔离级别的利器和基础了

当前读和快照读

  1. 快照读:只有普通的select语句是快照读,这里会生成一个快照,里面只有已提交的事务
  2. 当前读:比如select … for update或者insert或者update或者delete都是当前读,这里就会提交这里的数据。
  • 现在看是不是感觉没区别,等一会MVCC到RR的时候你们就会发现明显区别**(其实也很明显,只有快照读可以访问版本链,而当前读直接读最新数据来)**
  • 而RR级别为什么不可以完全解决幻读也是因为这里的当前读和快照读的冲突

数据库隐藏字段

首先是数据库隐藏字段

  1. DB_TRX_ID:这个是最近修改事务的ID
  2. DB_ROLL_PTR:这个是回滚指针,指向上一次事务的修改,也就是指向上一个版本
  3. DB_ROW_ID:这个是隐藏主键,如果没有主键字段就是用这个做主键

undolog版本链

概念

undolog是事务原子性的基础,当我们执行一条非查询的语句,比如insert,这里的undolog就会生成一个对应的delete,用于回滚,而这里的日志更新时机就是在执行语句真正执行前,这里就更新了日志(防止你断个电啥的造成损失,即使宕机,也可以回滚)
而undolog的第二个作用就是来帮我生成一个版本链(如图所示),这里就像链表,这里的头节点是最新的记录,每次使用头插法来插入新版本

快照读的相关属性

这里直接贴一张来自黑马程序员的图,我们一会讲案例的时候回来查

数据链访问规则(快照读)
  • 注意
    • 这里RR和RC的区别就是在于这里,RR每个事务只有一张快照,但是RC每次查询都会有快照,这个时候就会导致一个问题就是每次RC其实查询到的就是最新的已提交的数据(这个时候就触发了不可重复读和幻读),但是不用判断这里的数据链访问规则
    • 所以说这里的数据链访问规则就是给RR准备的,那我们看看这里是如何访问数据链的
    • 这里首先你要先去上面看ReadView的属性,在这个数据链访问规则还是很重要的
  • 比如这里我们的m_ids就是1,3,5(但是要注意快照读访问的就是已提交的事务,这里相当于一个黑名单)
  1. 关于这里的第一条规则,没什么说的,我创建的我还不可以访问了?
  2. 关于第二条规则,这里就是不在黑名单里面你就相当于提交了,所以这里可以访问
  3. 如果大于max就说明你不在我这个快照里面,无法读
  4. 第四个就说这个如果不在黑名单就可以访问
临键锁 <next-key锁>(当前读)

在RR隔离级别里面,对于当前读的防范就在这里,这里就是临键锁(行锁+间隙锁)
行锁可以防止不可重复读的问题,间隙锁可以避免大部分幻读问题(比如访问1,3,这里就会(-∞,1], (1,3], (3,+∞)锁住,防止别的线程插入数据),但是相应的这里的并发性能就会下降,因为其他的线程阻塞了
我们来一个例子理解一下,我们就看一下这个InnoDB在RR对临键锁的优化吧

比如我们现在有一组数据:10,20,20,30,40对应id:1,2,4,5,6

  1. 对于第一种情况:我们找一个id=3吧,就临键锁锁住这里的2-4,然后发现3不在,把临键锁退化为间隙锁,防止这里另一个进程插入一个3导致幻读
  2. 对于第二种情况:这里我们建立一个索引吧,然后通过这个索引来找这里=20的值,这里(10,20]加临键锁,(20,20]临键锁,(20-30]加临键锁。(如果这里没有20的话,这里就会锁(10,30)并且退化为间隙锁<第一种情况>)
    - 易困惑点:这里其实只需要锁一下这两条20以及这里的间隙就够了。但是这里其实多锁了一个30,因为这里数据命中了,这里无法从临键锁退化到间隙锁
  3. 对于第三种情况:这里我们查询id<4的值吧,这里(-∞,1]临键锁,(1,2]加临键锁,(2,4)加间隙锁
    - 目的:防止对这里id<4的值做改动
无法解决的冲突(RR)

看似这里我们有undolog版本链来防范快照读的幻读,有临键锁来防范当前读的幻读,那还有什么幻读是我们干不了的,这里能有什么问题。那其实小林coding就给出了两个场景,那也就是我们定义里面说的两个定义

  1. 场景一
    这里我们线程A来查询一下数据5,表中没有,所以查询不出来,这里线程B插入了一个数据5,现在A再来查询(快照读当然查不出来),这个时候A对数据5做一个更新操作(当前读当然可以更新),这个时候再去读,这个时候发现这个操作id是自己,就可以读到了
  2. 场景二
    这里我们线程A查询一下>100的数据,发现有3条,然后这个时候B插入一条200,这个时候A使用for update查询,发现有4条,就是我们说的SQL的经典幻读定义(这里的解决方案就是这里一旦开启事务就使用for update,也就是统一使用当前读
  • 其实总结来看,就是一个事务使用了当前读和快照读导致两种读法出现冲突

尾声

其实从企业的方面来看,他们不在乎不可重复读和幻读,只要不出现脏读就好,所以这里其实大家都为了这个并发性能大多业务都是RC,而这里的RR,只有涉及一些重要业务的时候使用,包括一些别的数据库,默认都是RC,所以说我觉得只需要重点关注一下RR和RC就好

http://www.jsqmd.com/news/907327/

相关文章:

  • Docker 网络进阶:容器间通信与 DNS 解析
  • 百度网盘提取码智能查询:3步告别资源获取烦恼的终极指南
  • 别再只关RST了!深入聊聊Intel快速存储技术(RAID)与Ubuntu/Linux的‘爱恨情仇’
  • Arduino旋转电位器应用:从模拟信号读取到Processing数据可视化
  • 不是所有 AI 产品都适合出海,真需求和全球化幻觉差在哪? | 嗨点小圆桌
  • 从压电传感器到示波器:手把手教你搭建电荷放大器与低通滤波器(含Multisim仿真与PCB焊接避坑指南)
  • Jetson Orin Nano + DeepStream 6.2 实战:将YOLOv5模型集成到生产级视觉流水线
  • Python爬虫实战:批量下载校园风光图
  • 10427条密码产品证书全部收集到,我发现几个数据跟认知完全对不上
  • 如何查物种的12S基因片段是否存在于NCBI公共数据库?
  • 别再傻傻用软件SPI了!实测STM32硬件SPI驱动GC9A01屏幕,速度提升10倍(附完整代码)
  • 打破大模型 KV Cache 魔咒:一种让跨模型 Agent 缓存 99% 命中的动态工具注入方案
  • 从音响制造到AI家庭娱乐生态:不见不散AI智能K歌音响亮相第二十届深圳国际金融博览会
  • 百年名校焕新光智底座,华为“领航”光智共融
  • Windows电脑也能玩转AI大模型!6G显存就能本地部署,免费无限用!
  • 北斗导航“指路”申通西安转运中心让特产寄递跑出“加速度”
  • 3D点云处理新思路:ParSeNet如何用“聚类+拟合”两阶段网络搞定复杂曲面重建?
  • Arduino电子钢琴DIY:从电路设计到C++编程的嵌入式音乐项目实践
  • 用鼠标单击我的电脑桌面图标或单击文件夹会自动变成重命名状态
  • Unity 2019.3+ 项目从内置管线迁移到URP的保姆级避坑指南(含材质修复)
  • 别只盯着地图!深度解析ArcGIS Pro内容窗格的5个隐藏选项卡(选择、编辑、捕捉…)
  • 手把手教你用阿里云服务器本地部署AWS DeepRacer训练环境(避坑指南)
  • 量子采样经典算法:突破NISQ时代组合优化瓶颈
  • 0104摩尔定律死亡终审:性能提升唯一路径——放弃几何微缩,转向场域升维+时间重构
  • 亚控组态数据导出踩坑实录:报表保存为Excel时文件名乱码、数据错位的解决办法
  • docker 实战:将一个多组件应用完整容器化
  • 新手也能搞定的TPS5430电源设计:从24V到15V,手把手教你选对每个元器件(附完整BOM清单)
  • 别再只用欧氏距离了!用Python实战Hausdorff距离,搞定图像匹配与异常检测
  • Unity游戏特效实战:用LineRenderer复刻红警磁暴闪电(附完整C#源码)
  • ArcMap新手必看:三种要素选择方法(按属性、位置、图形)的保姆级图文教程