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

MySQL数据库————MVCC

MySQL的脏读、幻读、不可重复读

脏读

在这里插入图片描述

现在有两个事务在操作table表,事务B修改了id=2的name字段为李老四,但是没有提交,事务A查询id=2的数据,得到name为李老四;事务B发生回滚,id=2的数据的name又变回李四,这时候事务A得到的name的值还是李老四,也就是说事务A读取到了别的事务未提交的数据,这就是脏读。

幻读

在这里插入图片描述
事务A,查询table表,获取到一条id=2,name='李四’的数据,紧接着,事务Adelete掉了table的数据,这时候table应该为空;在A处理其他任务时,事务B向table表中添加了一条id=3,name='王五’的数据,等事务A再次查询table表时,发现多出来一条数据,一次事务前后数据量发生变化,这就是幻读。

不可重复读

在这里插入图片描述
事务A查询table表中id=2的数据,得到name的值为李四,接着事务A处理其他任务,期间事务B修改了id=2的数据的name为李老四,并且提交。等事务A再一次查询table中id=2的数据,发现name的值变了为李老四。一个事务前后两次查询同一条数据,值不相同,这就是不可重复读。

小结

脏读:指读取到了其他事务正在处理还未提交的数据
幻读:指在并发情况下,新增、删除这种会产生数据量变化的操作时,另一个事务前后查询相同数据时不符合预期
不可重复读:指并发更新时,另一个事务前后查询相同数据时,数据不符合预期

事务隔离级别

隔离级别脏读不可重复读幻读加锁读
READ UNCOMMITTED
READ COMMITTED
REPEATABLE READ是(InnoDB除外)
SERIALIZABLE

如何修改隔离级别

# 获取当前事务隔离级别
SHOW VARIABLES LIKE 'transaction_isolation';
# 设置当前会话事务隔离级别
SET SESSION TRANSACTION ISOLATION LEVEL 级别;

MVCC

在MySQL InnoDB存储引擎下READ COMMITTED、REPEATABLE READ(多版本并发控制)进行并发事务控制,MVCC是基于“数据版本”对并发事务进行访问。
在这里插入图片描述

  • RR隔离级别
    • 结果:select 1,name=‘王五’;select 2,name=‘王五’
    • 过程:select1在查询时事务A已经提交,事务B未提交,所以name为王五,select2查询时,即便事务B已提交,由于隔离级别为可重复读,所以name还是王五
  • RC隔离级别
    • 结果:select1,name=‘王五’;select2,name=‘王老五’
    • 过程: select1在查询时事务A已经提交,事务B未提交,所以name为王五,select2查询时,事务B已提交,隔离级别又是读已提交,所以结果为name=‘王老五’

基于UNDO_LOG版本链

在这里插入图片描述

每一条数据链都会保存修改这条数据时的事务的id(自增),以及上一版本的数据链的地址和本次修改后的表数据的值。

ReadView

ReadView是“快照读”,SQL执行时MVCC提取数据的依据。快照读就是普通的select查询,当前读指在执行insert、update、delete、select…for…update、select…lock in share mode等语句时进行数据读取的方式。

ReadView结构

Read View是一个数据结构:

字段名含义
trx_list当前活跃的事务id集合
up_limit_id最小活跃事务id
low_limit_id预分配事务id,当前最大事务id+1

版本链数据访问规则:

  1. 判断DB_TRX_ID < up_limit_id,如果成立,则当前事务可以看到DB_TRX_ID所在的记录,反之则进行下一个判断
  2. 判断DB_TRX_ID >= low_limit_id,如果成立,则代表DB_TRX_ID所在的记录在ReadView生成后才出现的,那么对于当前事务肯定是不允许访问,如果不成立,进入下一步判断
  3. 判断DB_TRX_ID是否存在与活跃事务集合trx_list中,如果在,说明ReadView生成时,这个事务还是活跃的,还没有commit提交修改的数据,当前事务不允许访问,如果不在,则说明ReadView生成时,已经提交了修改结果,可以访问。

读已提交(RC)

在每一次执行快照读时生成新的ReadView。
分析事务D两次查询时的ReadView

  • select1

trx_list={2,3,4},
up_limit_id=2,
low_limit_id=5

  • select2

trx_list={3,4},
up_limit_id=3,
low_limit_id=5

在select1时,当前事务DB_TRX_ID=3,up_limit_id=2,DB_TRX_ID < up_limit_id不成立,进行下一步判断;low_limit_id=5,DB_TRX_ID >= low_limit_id不成立,所以进行第三步判断;DB_TRX_ID存在于trx_list中,是活跃的,不允许访问,接着同样的方法分析DB_TRX_ID=2。当DB_TRX_ID=1时,DB_TRX_ID < up_limit_id成立,所以可以访问。所以查到的数据是name=‘王五’。
在select2时,当前事务DB_TRX_ID=3,up_limit_id=2,DB_TRX_ID < up_limit_id不成立,进行下一步判断;low_limit_id=5,DB_TRX_ID >= low_limit_id不成立,所以进行第三步判断;DB_TRX_ID存在于trx_list中,是活跃的,不允许访问,接着同样的方法分析DB_TRX_ID=2。DB_TRX_ID=2时,前两步判断不成立,第三步时,DB_TRX_ID=2不存在于trx_list中,说明DB_TRX_ID=2的数据已经是commit的,所以可以访问,所以结果是name=‘王老五’。

可重复读(RR)

和上述RC过程一样,不同点在于,RR隔离级别,在一次事务中只在第一次快照读的时候生成ReadView,后面的快照读都会服用第一次生成的ReadView,所以,select1和select2的结果都是name=‘王五’。(特例:如果在两次快照读之间,存在了当前读,那么ReadView会重新生成,导致产生幻读)

http://www.lryc.cn/news/15977.html

相关文章:

  • 为啥Python多线程爬虫跑的慢?
  • 万字长文解析!复现和使用GPT-3/ChatGPT,你所应该知道的
  • Kaldi语音识别技术(八) ----- 整合HCLG
  • day17_异常
  • vue中把node-sass换成dart-sass方式(解决办法)
  • 深入浅出深度学习Pytroch
  • CCNP350-401学习笔记(451-500题)
  • 3年功能测试经验,面试想拿到15k很难吗?
  • 【7/101】101次面试之测试技术面试题
  • 【蓝桥杯每日一题】前缀和算法
  • 【C#基础】C# 常用数据结构
  • MySql 及MyBatis数据的批量操作
  • 无代码表格数据库——一个企业数字化新物种
  • 第十三届蓝桥杯国赛 C++ C组 F 题、Python B组 E 题——近似GCD(AC)
  • 分享5款小众良心软件,好用到让人惊艳
  • WAF是什么?一篇文章带你全面了解WAF
  • django项目实战八(django+bootstrap实现增删改查)进阶验证码
  • IP 协议
  • 好用的SQL工具盘点:从学习到工作总有一款适合你
  • Memcache介绍
  • PTA:C课程设计(1)
  • 第二十篇 ResNet——模型讲解
  • LeetCode经典算法题:矩阵中省份数量经典题目+三角形最大周长java多种解法详解
  • Vue3通透教程【一】Vue3现状—必然趋势?
  • 打破数据孤岛,Apache Doris 助力纵腾集团快速构建流批一体数仓架构|最佳实践
  • 什么是真正的骨传导耳机,骨传导耳机原理
  • [MySQL]基本数据类型及表的基本操作
  • 华为OD机试 - 好朋友(Python) | 机试题+算法思路+考点+代码解析 【2023】
  • SAP ABAP用程序给用户增加SAP_ALL权限
  • stm32f407探索者开发板(二十)——独立看门狗实验