一条记录的多幅面孔-事务的隔离级别与 MVCC

news/2024/12/29 23:07:11/

一、事务隔离级别

  1. 引出:**事务的隔离性要求,**理论上在某个事务对某个数据进行访问时,其他事务应该进行排队,当该事务提交之后,其他事务才可以继续访问这个数据。我们既想保持事务的 隔离性 ,又想让服务器在处理访问同一数据的多个事务时性能尽量高些舍一部分 隔离性 而取性能者也。
  2. 事务并发执行遇到的问题
    (1)脏写一个事务修改了另一个未提交事务修改过的数据
    (2)脏读一个事务读到了另一个未提交事务修改过的数据
    (3)不可重复读:如果一个事务只能读到另一个已经提交的事务修改过的数据,并且其他事务每对该数据进行一次修改并提交后,该事务都能查询得到最新值
    (4)幻读:一个事务先根据某些条件查询出一些记录,之后另一个事务又向表中插入了符合这些条件的记录,原先
    的事务再次按照该条件查询时,能把另一个事务插入的记录也读出来。幻读重点强调了读取到了之前读取没有获取到的记录
  3. SQL标准中的四种隔离级别
    (1)READ UNCOMMITTED :未提交读
    (2)READ COMMITTED :已提交读
    (3)REPEATABLE READ :可重复读
    (4)SERIALIZABLE :可串行化
    各个隔离级别下,允许发生的事务并发下遇到的问题
    在这里插入图片描述
    注意:因为脏写这个问题太严重了,不论是哪种隔离级别,都不允许脏写的情况发生。
  4. MySQL中支持的四种隔离级别
    注意:MySQL在REPEATABLE READ隔离级别下,是可以禁止幻读问题的发生的。与sql标准中规定有出入。MySQL 的默认隔离级别为 REPEATABLE READ(可手动修改)。

二、MVCC原理

  1. 版本链
    前言对于使用 InnoDB 存储引擎的表来说,它的聚簇索引记录中都包含两个必要的隐藏列:
    (1)trx_id :每次一个事务对某条聚簇索引记录进行改动时,都会把该事务的 事务id 赋值给 trx_id 隐藏列
    (2)roll_pointer :每次对某条聚簇索引记录进行改动时,都会把旧的版本写入到 undo日志 中,然后这个隐藏
    列就相当于一个指针,可以通过它来找到该记录修改前的信息(找到对应的undo日志)。

    版本连介绍展示如下:在这里插入图片描述在这里插入图片描述
    可以看到,第一张图中的两个事务的sql操作语句,形成了一个版本链(包括最新的记录和undo日志)。每个版本中还包含生成该版本时对应的 事务id
  2. ReadView
    ReadView 中主要包含4个比较重要的内容:
    (1)m_ids :表示在生成 ReadView 时当前系统中活跃的读写事务的 事务id 列表。
    (2)min_trx_id::m_ids 中的最小值。
    (3)max_trx_id:表示生成 ReadView 时系统中应该分配给下一个事务的 id 值。
    (4)creator_trx_id :表示生成该 ReadView 的事务的 事务id 。
    ReadView的作用需要判断一下版本链中的哪个版本是当前事务可见的
  3. ReadView的例子介绍
    (1)在 MySQL 中, READ COMMITTED 和 REPEATABLE READ 隔离级别的的一个非常大的区别就是它们生成ReadView的时机不同
    首先看在 READ COMMITTED 隔离级别下的。在这里插入图片描述

开启二个事务(id=100,200),在id=100的事务中修改名字的值,二个事务均未提交。然后通过查询语句,查询语句执行时候会生成一个ReadView,它的m_ids列表为[100, 200],min_trx_id 为 100 , max_trx_id 为 201 , creator_trx_id 为 0 。那么这次查询到的结果是版本号小于min_trx_id(100)的,所以查到的是 ‘刘备’。
之后提交一下id=100的事务,再次查询时候,会新生成一个ReadView, 它的m_ids列表为[200],min_trx_id 为 200 ,
max_trx_id 为 201 , creator_trx_id 为 0 。那么此时就需要版本号满足小于min_trx_id(200)的才能查询到,所以查到的是’张飞’。
总结一下就是:使用READ COMMITTED隔离级别的事务在每次查询开始时都会生成一个独立的ReadView。

然后再看在 REPEATABLE READ 隔离级别下的。
这个与上一个的区别就是,只会在一个事务中第一次查询建立ReadView,那么对应到上一个修改名字的例子就是,在两个事务均未提交时候,执行查询语句时会生成一个ReadView, 它的m_ids列表为[100, 200],min_trx_id 为 100 , max_trx_id 为 201 , creator_trx_id 为 0 。查询到的是 ‘刘备’。
之后提交一下id=100的事务,再次查询时候,会使用 原来的ReadView,所以查询到的还是 ‘刘备’。这也和这种隔离级别(REPEATABLE READ)很符合(可重复读)。
4. MVCC小结
从上边的描述中我们可以看出来,所谓的 MVCC (Multi-Version Concurrency Control ,多版本并发控制)指的就
是在使用 READ COMMITTD 、 REPEATABLE READ 这两种隔离级别的事务在执行普通的 SEELCT 操作时访问记录的版
本链的过程,这样子可以使不同事务的 读-写 、 写-读 操作并发执行,从而提升系统性能。
READ COMMITTD 、
REPEATABLE READ 这两个隔离级别的一个很大不同就是:生成ReadView的时机不同,READ COMMITTD在每一
次进行普通SELECT操作前都会生成一个ReadView,而REPEATABLE READ只在第一次进行普通SELECT操作
前生成一个ReadView,之后的查询操作都重复使用这个ReadView就好了。


http://www.ppmy.cn/news/48594.html

相关文章

职场危机波及到你了吗?社科院与杜兰大学金融管理硕士项目为你重塑核心竞争力

现在职场,危机四伏,每个人都面临着潜在的危机。职场小白,时时忧心自己的工作是否出错,是否能安全度过试用期;面对新人辈出,职场的前辈也担心被拍在沙滩上。面对竞争激烈的职场,你有感到危机吗&a…

Vue.js过滤器filters

目录 一、局部过滤器 二、全局过滤器 三、过滤器串联 四、过滤器接收多个参数 Vue.js允许自定义过滤器,过滤器的作用可被用于一些常见的文本格式化(也就是修饰文本,但是文本内容不会改变) 过滤器可以用在两个地方&#xff1a…

虚化背景 - 基于镜头模糊滤镜的深度映射

镜头模糊 Lens Blur等滤镜可以使用深度映射 Depth Map来设置像素在视觉上的前后关系。因此,常利用深度映射来创建真实感虚化效果,或者进行超越镜头的任意虚化处理。 ◆ ◆ ◆ 基于 Alpha 通道的深度映射关系 一般可通过建立 Alpha 通道或图层蒙版来创建…

Vivado增量编译:加速FPGA设计实现的利器

随着FPGA设计的复杂度不断提高,设计人员需要选择更为高效的设计流程来保证开发效率和减少开发成本。其中,Vivado增量编译是一种非常重要的设计流程。本文将介绍Vivado增量编译的基本概念、优点、使用方法以及注意事项。 通过阅读本文可以了解&#xff1…

怎么将太大的word文档压缩变小,3个高效方法

怎么将太大的word文档压缩变小?word文档是我们在办公中使用较多的文件格式之一,相信小伙伴们会遇到这样的问题,编辑完成word文档之后发现,编辑完的文档体积太大了,无论是发送给客户还是上传到邮箱中都不方便&#xff0…

汉诺塔问题--C语言实现

魔王的介绍:😶‍🌫️一名双非本科大一小白。魔王的目标:🤯努力赶上周围卷王的脚步。魔王的主页:🔥🔥🔥大魔王.🔥🔥🔥 ❤️‍&#x1…

【Linux】基于单例模式懒汉实现方式的线程池

目录 一、LockGuard.hpp 二、Task.hpp 三、Thread.hpp 四、ThreadPool.hpp 一、LockGuard.hpp #pragma once #include <iostream> #include <pthread.h> class Mutex//锁的对象 { public:Mutex(pthread_mutex_t* lock_pnullptr):_lock_p(lock_p){}~Mutex(){}v…

光栅和矢量图像处理SDK:Graphics Mill 11.7Crack

Graphics Mill 是适用于 .NET 和 ASP.NET 开发人员的最强大的成像工具集。它允许用户轻松地向 .NET 应用程序添加复杂的光栅和矢量图像处理功能。 光栅图形 加载和保存 JPEG、PNG PSD 和其他 8 种图像格式 调整大小、裁剪、自动修复、色度键和 30 多种其他图像处理 使用任何维度…