Mysql-事务(隔离级别,事务底层原理,MVCC)

什么是事务?有哪些特性?

事务:事务指的是逻辑上的一组操作,组成这组操作的各个单元要么全都成功,要么全都失败。
事务特性:

  • 原子性(Atomicity): 原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。
  • 一致性(Consistency):事务前后数据的完整性必须保持一致
  • 隔离性(Isolation):多个用户并发访问数据库时,一个用户的事务不能被其它用户的事务所干扰,多个并发事务之间数据要相互隔离。隔离性由隔离级别保障。
  • 持久性(Durability): 一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响。

事务并发可能产生那些问题?

1 脏读:一个事务读到了另一个事务未提交的数据
2 不可重复读:一个事务读到了另一个事务已经提交(update)的数据。引发事务中的多次查询结果不一致,数据中的值不一致。
3 虚读 /幻读:一个事务读到了另一个事务已经插入(insert)的数据。导致事务中多次查询的结果不一致,比如一个事务向表中插入了一条数据,这个时候另一个事务读取到了这条数据这就是幻读,实际上不应该读到这条数据。
4 丢失更新,举个例子比如事务T1,T2都读取了表中的某一行数据,事务T1对一个表的数据做了更新更为值A,事务T1提交以后,T2也对这个数据进行了修改改为B并提交,这个时候在事务T1里面查询这个数据得到的值是B,T1对数据的修改A被丢失了。
导致这个问题的根本原因就是并发问题,这两个事务可以同时对这个数据进行修改

事务的隔离级别

1 read uncommitted 读未提交【RU】,一个事务读到另一个事务没有提交的数据
存在:3个问题(脏读、不可重复读、幻读)。
2 read committed 读已提交【RC】,一个事务读到另一个事务已经提交的数据
存在:2个问题(不可重复读、幻读)。
解决:1个问题(脏读)
3 repeatable read:可重复读【RR】,在一个事务中读到的数据始终保持一致,无论另一个事务是否提交
解决:3个问题(脏读、不可重复读、幻读)msql默认的隔离级别
4 serializable 串行化,同时只能执行一个事务,相当于事务中的单线程
解决:3个问题(脏读、不可重复读、幻读)

事务的底层原理

前面我们提到了四个问题,我们来解决这些问题。

解决方案一:基于锁并发控制LBCC

1 解决丢失更新的问题
我们在事务T1读取这样行数据的时候就直接加读锁,这个时候T2想要来修改这个数据需要加写锁是不被允许的,就必须等待这个读锁释放,T2才能对对数据进行更新,锁释放的时候事务T1已经执行完成,保证了不会丢失事务T1的更新。
在这里插入图片描述
2 解决读已提交(Read Committed)
读取数据的事务允许其他事务继续访问该行数据,但是未提交的写事务将会禁止其他事务访问该行。这可以通过“瞬间共享读锁”和“排他写锁”实现, 即事务需要对某些数据进行修改必须对这些数据加 X 锁,事务结束后才会释放X锁,读数据时需要加上 S 锁,当数据读取完成后立刻释放 S 锁,不用等到事务结束。

3 解决可重复读取(Repeatable Read)
禁止不可重复读取和脏读取,但是有时可能出现幻读数据。读取数据的事务将会禁止写事务(但允许读事务),写事务则禁止任何其他事务。
Mysql默认使用该隔离级别。这可以通过“共享读锁”和“排他写锁”实现,即事务需要对某些数据进行修改必须对这些数据加 X 锁,读数据时需要加上 S 锁,当数据读取完成并不立刻释放 S 锁,而是等到事务结束后再释放。

解决方案二:基于版本并发控制MVCC

MVCC全称叫多版本并发控制,是RDBMS常用的一种并发控制方法,用来对数据库数据进行并发访问,实现事务。核心思想是读不加锁,读写不冲突。在读多写少的OLTP应用中,读写不冲突非常重要,极大的增加了系统的并发性能,这也是为什么几乎所有的RDBMS,都支持MVCC的原因。MVCC 实现原理关键在于数据快照,不同的事务访问不同版本的数据快照,从而实现事务下对数据的隔离级别。虽然说具有多个版本的数据快照,但这并不意味着必须拷贝数据,保存多份数据文件(这样会浪费存储空间),InnoDB通过事务的Undo日志巧妙地实现了多版本的数据快照。
这里介绍一下UndoLog
InnoDB 引擎对一条记录进行操作(修改、删除、新增)时,要把回滚时需要的信息都记录到 undo log 里,比如:
1)在插入一条记录时,要把这条记录的主键值记下来,这样之后回滚时只需要把这个主键值对应的记录删掉
2)在删除一条记录时,要把这条记录中的内容都记下来,这样之后回滚时再把由这些内容组成的记录插入到表中.
3)在更新一条记录时,要把被更新的列的旧值记下来,这样之后回滚时再把这些列更新为旧值
会产生两种日志:
1 insert Undo 日志:在Insert操作中产生的Undo日志
由于insert操作的记录只对本身可见,对于其它事务此记录是不可见的,所以insert undo log 可以在事务提交后直接删除,不需要等待回收
在这里插入图片描述
2 Update Undo日志:Update或Delete 操作中产生的Undo日志
Update操作会对已经存在的行记录产生影响,为了实现MVCC多版本并发控制机制,因此Update Undo日志不能在事务提交时就删除,而是在事务提交时将日志放入指定区域,等待 Purge 线程进行最后的删除操作。
在这里插入图片描述
这个时候比如我们需要对第二次更新做回滚操作,这个时候只需要顺着RollPointer指针回退一个版本。

有了上面的Undo Log 我们可以结合是ReadView来实现版本控制
ReadView
ReadView是张存储事务id的表,主要包含当前系统中有哪些活跃的读写事务,把它们的事务id放到一个
列表中。结合Undo日志的默认字段【事务trx_id】来控制那个版本的Undo日志可被其他事务看见。

在这里插入图片描述
m_ids:表示在生成ReadView时,当前系统中活跃的读写事务id列表
m_low_limit_id:事务id下限,表示当前系统中活跃的读写事务中最小的事务id,m_ids事务列表中的最小事务id
m_up_limit_id:事务id上限,表示生成ReadView时,系统中应该分配给下一个事务的id值
m_creator_trx_id:表示生成该ReadView的事务的事务id

  • ReadView怎么产生,什么时候生成?
    开启事务之后,在第一次查询(select)时,生成ReadView
    RC 和 RR 隔离级别的差异本质是因为MVCC中ReadView的生成时机不同
    MVCC 怎么保证事务的RC和RR隔离级别可以看这篇文章, 根据下面判断可见性的原理做了一个案例演示。
    MVCC + ReadView案例

  • 如何判断可见性?
    开启事务执行第一次查询时,首先生成ReadView,然后依据Undo日志和ReadView按照判断可见性,
    按照下边步骤判断记录的版本链的某个版本是否可见。

如果被访问版本的 trx_id 属性值,小于ReadView中的事务下限id,表明生成该版本的事务在生
成 ReadView 前已经提交,所以该版本可以被当前事务访问。
如果被访问版本的 trx_id 属性值,等于ReadView中的 m_creator_trx_id ,可以被访问。
如果被访问版本的 trx_id 属性值,大于等于ReadView中的事务上限id,在生成 ReadView 后才产生的数据,所以该版本不可以被当前事务访问。
如果被访问版本的 trx_id 属性值,在事务下限id和事务上限id之间,那就需要判断是不是在
m_ids 列表中。如果在,说明创建 ReadView 时生成该版本的事务还是活跃的,该版本不可以被访问;如果不在,说明创建 ReadView 时生成该版本的事务已经被提交,该版本可以被访问。

循环判断Undo log中的版本链某一的版本是否对当前事务可见,如果循环到最后一个版本也不可见的
话,那么就意味着该条记录对该事务不可见,查询结果就不包含该记录。

MVCC下的读操作

在MVCC并发控制中,读操作可以分成两类:快照读 (Snapshot Read)与当前读 (Current Read)
快照读:读取的是记录的可见版本 (有可能是历史版本),不用加锁。刚才案例中都是快照读。
当前读:读取的是记录的最新版本,并且当前读返回的记录,都会加上锁,保证其他事务不会再并发修改这条记录

  • 快照读
    简单的select操作,属于快照读,不加锁。
  • 当前读
    特殊的读操作,或者插入/更新/删除操作,属于当前读,需要加锁,需要读取最新的数据。
select * from table where ? lock in share mode; # 加读锁
select * from table where ? for update;# 加写锁
insert into table values ();# 加写锁
update table set ? where ?;# 加写锁
delete from table where ?;# 加写锁

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

低代码平台:业务开发“加速器”

一、现状 低代码开发平台要让每个人,包括开发者和普通业务人员,都能够成为企业数字化过程中的主导者和构建者!让普通人更容易上手! 基于这一目标,应用需求多的云服务商成为低代码投资的主要来源。一家云服务商如谷歌云…

JavaScript中的坐标

🧑‍🎓 个人主页:《爱蹦跶的大A阿》 🔥当前正在更新专栏:《VUE》 、《JavaScript保姆级教程》、《krpano》、《krpano中文文档》 ​ ​ ✨ 前言 在我们的日常生活中,JavaScript已经成为了一种无处不在的…

华为三层交换机与防火墙对接配置上网示例

三层交换机与防火墙对接上网配置示例 组网图形 图1 三层交换机与防火墙对接上网组网图 三层交换机简介配置注意事项组网需求配置思路操作步骤配置文件 三层交换机简介 三层交换机是具有路由功能的交换机,由于路由属于OSI模型中第三层网络层的功能,所以…

ERP系统在生产管理中的应用

随着市场竞争的加剧和企业业务范围的拓展,生产管理在企业运营中的地位日益凸显。为了提高生产效率、降低成本、优化资源配置,越来越多的企业开始引入ERP系统进行生产管理。云迈ERP系统为您提供全面的生产管理解决方案。 一、生产需求管理 在ERP系统中&a…

MYSQL基本查询(CURD:创建、读取、更新、删除)

文章目录 前言一、Create1.全列插入2.指定列插入3.插入否则更新4.替换 二、Retrieve1.SELECT列2.WHERE条件3.结果排序4.筛选分页结果 三、Update四、Delete1.删除数据2.截断表 五、插入查询结果六、聚合函数 前言 操作关系型数据库的编程语言,定义了一套操作关系型…

UE5在VisualStudio升级后产生C++无法编译的问题

往期的虚幻引擎项目在VS更新后,编译时会报错,这一般出现在VS升级之后,UE对于VC的编译器定位没有更新导致; 有出现如下问题: 问题1: Running I:/EPCI/Epic Games/UE_5.3/Engine/Build/BatchFiles/Build.ba…

如何优化博客的内容和用户体验

在当今数字时代,博客成为了分享知识、展示个人专业能力和吸引读者的重要工具。然而,随着越来越多的博客涌现,如何优化博客的内容和用户体验成为了一个关键的问题。本文将为你提供一些有效的技巧,帮助你优化博客的内容和提升用户体…

《少年派的奇幻漂流》观后感

《少年派的奇幻漂流》是一部充满奇幻、深度和美感的电影,由导演李安执导,基于亨利沃恩(Yann Martel)的同名小说改编而成。这部影片以惊人的视觉效果和富有哲学思考的故事而著称。 影片的视觉效果令人叹为观止。通过3D技术和出色的…

QT+VS实现Kmeans++

1、Kmeans的原理如下: (1)首先选取样本中任一数据点作为第一个聚类中心; (2)计算样本每一个数据点至现所有聚类中心的最近距离,并记录下来; (3)逐一挑选所…

基于springboot校园台球厅人员与设备管理系统源码和论文

在Internet高速发展的今天,我们生活的各个领域都涉及到计算机的应用,其中包括校园台球厅人员与设备管理系统的网络应用,在外国管理系统已经是很普遍的方式,不过国内的管理网站可能还处于起步阶段。校园台球厅人员与设备管理系统具…

mcu专用看门狗复位芯片(如MAX706)

mcu专用看门狗复位芯片(如MAX706) 为什么要使用电压复位芯片RESET引脚WDO引脚MR引脚WDI引脚 国产替代型号应用电路1 推荐电路(用一个跳线帽使能/关闭看门狗功能,调试MCU时防止看门狗芯片随便触发复位功能),…

Linux内存管理:(十)KSM内核同页合并

文章说明: Linux内核版本:5.0 架构:ARM64 参考资料及图片来源:《奔跑吧Linux内核》 Linux 5.0内核源码注释仓库地址: zhangzihengya/LinuxSourceCode_v5.0_study (github.com) 1. KSM定义 KSM指Kemel SamePage M…