【MySQL】事务(下)

news2024/11/22 23:05:00

文章目录

  • 1. 各个隔离级别的演示
    • 事务隔离级别 —— 读未提交
    • 事务隔离级别—— 读提交
    • 事务隔离级别 —— 可重复读
    • 事务隔离级别 —— 串行化
    • 脏读 不可重复读 幻读的理解
  • 2. MVCC机制
    • 读写
    • 3个记录隐藏列字段
    • undo日志
    • 模拟MVCC
    • read view 理论
  • 3. 读提交与 可重复读的区别
      • 两者本质区别

1. 各个隔离级别的演示

事务隔离级别 —— 读未提交

输入 select @@global.tx_isolation; 查询当前的隔离级别
发现 其隔离级别为 串行化


先将全局隔离级别 修改为 读未提交
再次查询发现 修改成功,全局隔离级别 已经被修改为 读未提交


在终端1中,启动事务后,插入王五的数据,此时在终端2中也可以查到王五的数据
再次在终端1的事务中 更新王五的名字为qwe, 此时终端2的事务中 依旧能查到 王五的名字已经修改为qwe

一个事务在执行中,读到另一个执行中的事务的更新 但是还没有commit的数据,这种现象叫做 脏读


事务隔离级别—— 读提交

将全局隔离级别 改为 读 提交


在终端1 启动事务后,插入 田七的数据到表中 ,此时在终端2启动事务的表中 是查询不到田七的数据
在终端1中再次修改id值为2的名字为liubei,此时在终端2中依旧是没有对id值为2的名字做出修改
当终端1的事务 进行 提交后 ,终端2中的事务才能查询到 表做出的修改数据

当一个事务,并未commit,就造成 同一个事务内,同样的读取,在不同的时间段,读取到不同的值
这种现象叫做 不可重复读


事务隔离级别 —— 可重复读

首先要保证终端1和终端2的全局隔离级别 和 会话隔离级别 都为 可重复读

输入 select @@global.tx_isolation; 查询当前会话的隔离级别
发现当前为 read -committed 表示 读提交


将会话的隔离级别 修改为 可重复读


查询当前全局隔离级别 也是 为 可重复读


启动事务后,在终端1中,插入王五的数据时,在终端2中,是是不见对应王五的数据的
终端1就算进行了提交,在终端2中也是看不见王五数据的


在终端2中,进行commit提交后,发现才可以查看到 account表中 修改的数据


可重复读对于删除 也是如此,当在终端1中 删除id值为2的数据时,终端2中是没有数据变化


只有当终端2进行提交,才可以看到终端1对表做出 的删除数据的操作


事务隔离级别 —— 串行化

保证mysql让所有的事务 进行串行化,就可以保证mysql 绝对的完整性
一个安全的方案,但并不是一个高效的方案


保证终端1和终端2的全局隔离级别 和 会话隔离级别都为 串行化

设置 全局隔离级别 修改为 串行化
并查看当前全局隔离级别


将会话隔离级别 修改为 串行化
并查看当前会话 隔离级别


在终端1中,当想进行删除id值为1的数据时,发现卡住了


在终端2中,当事务进行提交,终端1中的删除id值为1的数据 的操作 就可以正常生效了


脏读 不可重复读 幻读的理解


一个事务在执行中,读到另一个执行中事务的更新(或其他操作)但是未commit的数据,这种现象叫做脏读

(如在终端1中插入数据,而在终端2中是可以查询到数据的存在的)


同一个事务内,同样的读取,在不同的时间段,读取到了不同的值,这种现象叫做不可重复读

(如在终端1中查询数据,数据A是属于 50-100 范围内的,并且已经检测到数据A存在于50-100范围内, 但终端2在检测后修改数据A的范围 在100 -200 ,就会导致 终端1中继续检测时,发现 数据A还会存在于100-200 范围内)


一般的数据库在可重复读情况的时候,无法屏蔽其他事务insert的数据
会造成虽然大部分内容是可重复读的,但是insert的数据在可重复读
情况被读取出来,导致多次查找时,会多查找出来新的记录,就如同产生了幻觉。这种现象,叫做幻读

(少数的mysql版本 虽然在可重复读 情况下,但依旧无法避免 终端2 能够查询到终端1的数据
正常来说在 可重复读情况下,终端2是不可以接收到来自终端1的数据的)


可以发现 读未提交 是 会触发 脏读、不可重复读、幻读 的情况的,所以隔离级别很低
其次 是 读已提交是不会触发 脏读 ,但是会触发 不可重复读、幻读的情况的
可重复读 与 可串行化 都不会 触发 脏读 不可重复读 、幻读 的情况

2. MVCC机制

一个数据库在并发访问时,具体场景有:
读-读并发,不存在任何问题,也不需要并发控制(没有人修改)
写-写并发,有线程安全问题,可能会存在更新丢失的问题
读-写并发,有线程安全问题,可能会造成事务隔离问题,出现脏读、幻读、不可重复读问题


读写

多版本并发控制(MVCC) 是一种用来解决 读写冲突的无锁并发控制

事务一定是有先有后 到达的,如何区分事务的先后问题
每一个事务 都有自己的事务ID
可以根据事务ID的大小,来决定事务到来的先后顺序

mysqld 可能会面临处理多个事务的情况,事务也有自己的生命周期
(其生命周期指的是 其要被创建、投递到等待队列中、拿出来等待执行、执行错误进行回滚、执行完毕要被消除)
所以mysqld 要对多个事务进行管理,管理的本质是 先描述 在组织
就可以把 事务 看作 mysql中的一个结构体对象或者类对象,而事务ID是在结构体内部的


3个记录隐藏列字段

DB_TRX_ID : 6 byte 最近修改或插入的事务ID ,记录创建这条记录或最后一次修改该记录的事务ID
( 以插入举例,最近一次 插入记录的事务 是谁插入的,对应的事务ID是谁,把对应的事务ID放入表中)

DB_ROLL_PTR: 7byte ,回滚指针 指向这条记录的上一个版本

DB_ROW_ID: 6 byte 隐含的自增ID ,如果表中没有主键,InnoDB 会自动 以 DB_ROW_ID 产生一个聚簇索引


创建一张表 student,其中内部并不包含主键,只有一个不为空的name和不为空的age


将张三的数据 插入到 student表中


DB_TRX_ID 为 null ,说明没有事务进行插入、删除或者修改
DB_ROW_ID 为1 ,说明表中没有创建主键,所以使用隐含的主键
DB_ROLL_PTR 为null, 说明没有执行任何操作,找不到启动事务后的上一次操作


undo日志

mysql内有一大堆的日志缓冲区,就可以将其放入buffer pool中,被称为 undo log
undo log 是应用层 由mysql维护的一段内存缓冲区,用于保存日志数据


模拟MVCC

想要将上述创建好的student表中 张三数据做出修改, 事务10 通过使用 update 将张三 修改为 李四

msyql 判断要对事务进行修改,就需要先给 记录 加锁
修改前,需要先将记录拷贝到 undo log 中,此时undo log 中就有了一行副本数据


因为把老版本在 undo log 中保存了一份,所以在DB_ROLL_PTR 中填入对应老版本的地址 0xaa
该记录就指向了 undo log 中的历史版本
最终把 name 从张三 改到 李四
又因为 是事务10对表中数据做出修改,所以 对应的 DB_TRX_ID 变为10
当事务提交后,就在该记录下释放锁


如果又来了一个事务11,要把表中的记录 做出修改,把age 从 28 改为 30
msyql 判断要对事务进行修改,就需要先给 记录 加锁
修改前,需要先将记录拷贝到 undo log 中,此时undo log 中就又有了一行副本数据


因为把老版本在 undo log 中保存了一份,所以在DB_ROLL_PTR 中填入对应老版本的地址 0xbb
该记录就指向了 undo log 中的历史版本
又因为 是事务10对表中数据做出修改,所以 对应的 DB_TRX_ID 变为11、age 变为 30
当事务提交后,就在该记录下释放锁


最终形成一个多版本的数据,就称为 MVCC 多版本控制
把上述的一个一个的版本,称之为一个一个的快照


当前读:读取最近的记录
快照读:读取历史版本,不读取最新数据
增删改 都叫做当前读
select 有可能是当前读、也有可能是 快照读

读写并发:当使用upate对数据做修改时, 写 的是 当前最新的数据,而读的是 历史版本的数据
不会出现访问同一个的位置 ,就不用加锁,可以并发进行读写操作


串行化的 读写 访问的都是 当前数据,所以读写必须都加锁
若select 采用快照读,即读取历史版本的数据 ,是不受加锁限制的,就可以并发可以执行
既提高了效率,又为未来实现隔离性提供底层支持


read view 理论

read view 就是 事务进行快照读 操作的时候 产生的 读视图
在该事务执行的快照读的那一刻,会生成数据库系统当前的一个快照
记录并维护当前活跃事务的ID
(每个事务开启时,都会被分配一个ID,这个ID是递增的,所以最新事务,ID值越大)

read view 在mysql中就是一个类,本质是用来可见性判断的

当某个事务执行 快照读时,对该记录 创建一个read view 读视图,用它作为条件,用来判断当前事务能够看到那个版本的数据
,既可能是当前最新的数据,也有可能是 undo log 里面某个版本的数据


在read view类中 有四个重要字段
mids 表示 一张列表,用来维护read view 生成时刻,系统正在活跃的事务ID
(事务是并发的,当一个事务在运行时,其他事务也可能在运行,所以获取正在活跃的事务ID)

up_limit_id 表示 mids列表中 事务ID最小的ID
low_limit_id 表示 read view 生成时刻系统尚未分配的下一个事务ID,也就是目前已经出现的事务ID的最大值+1
creator_trx_id 表示 创建这个read view 的事务ID



若版本链某一条记录中的事务ID 与自己的creator_trx_id 相同
说明现在正在查看的记录,就是自己创建的,所以就应该看到对应的事务


up_limit_id 表示正在活跃的事务ID中最小的
若遍历对应的版本链时,发现对应的事务ID 比 我所能看到的最小的事务ID 还要小
说明 DB_TRX_ID 对应的事务早就已经 结束提交
所以我应该看到 该事务


low_limit_id 表示 read view 生成时刻系统尚未分配的下一个事务ID
若遍历版本链,发现所记录某一条的事务ID 比我自己事务中的 low_limit_id 还要大
说明 该事务 还没有跑起来


假设有 7 8 9 10 号事务ID,在快照前, 7 和 9 号事务ID 先提交了
所以 m_ids 中 就为 8 和 10 号 事务ID
所以快照到的事务ID 可以不连续
即 DB_TRX_id 不在 mid_s列表中,说明已经提交了,就可以看到
如果在,则说明该事务和自己的事务一样都是活跃事务,没有提交,就不应该看到


read view 是事务可见性的一个类,不是事务创建出来的时候,就会有read view
而是当这个事务(该事务已经存在), 首次进行快照读的时候,mysql 会形成 read view

3. 读提交与 可重复读的区别

RR (repeatable Read) 表示 可重复读

RC(Read Committed) 表示 读提交


select * from user lock in share mode 以加共享锁方式进行读取,对应的是当前读
若不加 lock in share mode 则为对照读


查询当前隔离级别 发现为 串行化


将隔离级别设置为可重复读


向user表中插入id值为1的数据
输入 select * from user 查看当前user表中的数据


由于select * from user 是快照读,读取的是历史版本的数据
所以即使当终端1将id值为1的数据 的age修改为18
终端2中 进行从查询 表中 id值为1的数据 的age 依旧为15

所以将其改成 select * from user lock in share mode , 此时就按照当前读
再次查询表中id值为1的数据的age 为18

假设终端1中的事务为 事务A ,终端2中的事务 为 事务B
事务B进行快照读时,mysql就已经形成了一个 read view
事务B 快照对象里面的值 认为 事务A 是跟它一块运行的
事务B 就认为 事务A 在自己的 mid_s 列表中,没有提交,就看不到


先在终端1进行修改age, 进行提交后再查询


此时 终端2才进行查询
则发现即使是快照读 ,表中数据也是修改后的,与 当前读 到的数据是相同的

假设终端1中的事务为 事务A ,终端2中的事务 为 事务B

由于事务B在 事务A进行操作时,并没有进行快照读,从而没有生成对应的 read view
只有到 事务A 进行提交后 , 事务B 才进行快照读 ,生成 read view
此时 事务B中 mid_s列表 中 不存在 事务A的值,说明 已经提交了 ,就可以看到了


先在终端1进行修改age, 进行提交后再查询


此时 终端2才进行查询
则发现即使是快照读 ,表中数据也是修改后的,与 当前读 到的数据是相同的

假设终端1中的事务为 事务A ,终端2中的事务 为 事务B

由于事务B在 事务A进行操作时,并没有进行快照读,从而没有生成对应的 read view
只有到 事务A 进行提交后 , 事务B 才进行快照读 ,生成 read view
此时 事务B中 mid_s列表 中 不存在 事务A的值,说明 已经提交了 ,就可以看到了

两者本质区别

RR (repeatable Read) 表示 可重复读

RC(Read Committed) 表示 读提交


由于read view 形成时机的不同,从而造成 RC、RR 级别下 快照读的结果的不同

RR级别下 的某个事务 的对某条记录的第一次快照读会创建 一个快照及 read view
将系统活跃的其他事务记录起来

只有当首次快照读时,才会产生 read view ,所以之后的快照读 使用的都是 同一个 read view ,对之后的修改不可见
(此时更新数据,全被放入 read view的mid_s列表中,说明没有提交 不可见)


在RC级别下, 事务中,每次快照读都会重新生成一个 快照 和 read view
所以一个终端中的事务 就可以看到另一个终端中的事务提交的更新

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

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

相关文章

分布式锁介绍

为什么需要分布式锁 在单机部署的系统中,使用线程锁来解决高并发的问题,多线程访问共享变量的问题达到数据一致性,如使用synchornized、ReentrantLock等。 但是在后端集群部署的系统中,程序在不同的JVM虚拟机中运行,且…

ISP 处理流程

#灵感# 摆烂时间太长了,感觉知识忘光光了。重新学习,常学常新。 因为公司文档都不让摘抄、截取,所以内容是工作的一些自己记录和网络内容,不对的欢迎批评指正。 1、ISP概述 ISP是Image Signal Processor 的简称,也就…

【计算机网络】VLAN原理和配置

目录 1、VLAN的原理 1.1、什么是VLAN 1.2、为什么要使用VLAN 1.3、VLAN的三种端口类型 1.4、VLAN的划分方法 2、VLAN的配置 1、VLAN的原理 1.1、什么是VLAN VLAN(Virtual Local Area Network)即虚拟局域网,是将一个物理的LAN在逻辑上…

key的性能保障,事件处理器,表单控件等介绍

4-2key设置-性能的保障 不能修改原数组的方法,如果想要修改原数组,就进行重新赋值 this.items this.items.filter((item) > item.message.match(/Foo/)) keyCode键的值**key设置-性能的保障**提高性能,可以对比老的虚拟dom,一样的就留着,不一样就补上Vue默认按照"就地…

2024年孝感初中级工程师职称评审要求

孝感工程类初级职称、中级职称职称评审相关要求,满足什么条件可以评审孝感职称呢?秋禾火告诉你 什么人可以在孝感申报职称 1.在孝感本地注册登记1年以上,按规定缴纳社保的的制造业、建筑业等生产类民营企业。2.参加评审的人员与所属企业签订…

使用CXF调用WSDL(二)

简介 本篇文章主要解决了上篇文章中遗留的对象嵌套问题,要想全面解析无限极的对象嵌套需要使用递归去解决 上文链接: 使用CXF调用WSDL(一) 上文回顾 上文使用了单方法“ call() ”解决了List和基本类型(含String&…

用户登录信息如何存放

放到ThreadLocal LoginUserInfoDto 缓存登录信息的实体,我这里只放了一个手机号就够了。可以根据自己的需要修改,比如角色权限等等 package com.fox.domain.dto;/*** author * 当前登录人信息*/ public class LoginUserInfoDto {/*** 当前登录人 手机号…

什么是变更管理?对IT管理有什么帮助?

变更管理是指在最短的中断时间内完成基础架构,或服务的任一方面的变更而对其进行控制的服务管理流程。变更管理的目标是确保在变更实施过程中使用标准的方法和步骤,尽快地实施变更,以便最小化由变更所导致的业务中断,将变更对业务的影响减小到…

使用Tauri开发桌面应用

本文是对视频 Tauri入门教程[1]的学习与记录 Tauri官网[2] 对 node版本有要求 创建项目及目录介绍: 项目的目录结构如下 可以安装推荐的插件 执行npm run tauri build出错,根据 https://github.com/tauri-apps/tauri/issues/7430 执行 yarn add -D tauri-apps/cli && y…

【Windows】安装绿色版Mysql数据库 -- 可支持所有版本安装教程

👨‍🎓博主简介 🏅云计算领域优质创作者   🏅华为云开发者社区专家博主   🏅阿里云开发者社区专家博主 💊交流社区:运维交流社区 欢迎大家的加入! 🐋 希望大家多多支…

【Python数据结构与算法】线性结构小结

🌈个人主页: Aileen_0v0 🔥系列专栏:PYTHON学习系列专栏 💫"没有罗马,那就自己创造罗马~" 目录 线性数据结构Linear DS 1.栈Stack 栈的两种实现 1.左为栈顶,时间复杂度为O(n) 2.右为栈顶,时间复杂度O(1) 2.队列Queue 3.…

SpringCloudalibaba2

一、nacos简介 Nacos(全称为"Nano Service")是一个用于动态服务发现、配置管理和服务元数据的开源平台。它由阿里巴巴集团于2018年开源,并逐渐成为云原生应用中的重要组件之一。 Nacos提供了以下主要功能: 1. 服务发…

Mysql5.7创建远程账号和新建数据库

文章目录 Mysql5.7创建远程账号和新建数据库创建远程账号新建默认数据库默认数据库指定字符集数据库写法一写法二 查看数据库列表查看数据库的定义声明 Mysql5.7创建远程账号和新建数据库 创建远程账号 CREATE USER mm% IDENTIFIED WITH mysql_native_password BY mm1122;Que…

iceoryx(冰羚)-Service Discovery

Service Discovery Summary and problem description IPC通道(例如消息队列或UNIX域套接字)上的服务发现是不可执行的,因为传输的数据较大,这可能会导致多个帧的传输。如果发现大量高频服务,例如在启动时&#xff0c…

易点易动固定资产管理系统助您轻松应对复杂的固定资产管理挑战

在现代企业运营中,固定资产是企业的重要财产,对于企业的发展和运营至关重要。然而,随着企业规模的扩大和业务的复杂化,固定资产管理面临着越来越多的挑战。传统的手工管理方法已经无法满足企业的需求,因此,…

Sentinel底层原理(下)

1、概述 Sentinel的核心原理,也就是前面提到暗流涌动的SphU.entry(…)这行代码背后的逻辑。 Sentinel会为每个资源创建一个处理链条,就是一个责任链,第一次访问这个资源的时候创建,之后就一直复用,所以这个处理链条每…

开源软件 FFmpeg 生成模型使用图片数据集

本篇文章聊聊,成就了无数视频软件公司、无数在线视频网站、无数 CDN 云服务厂商的开源软件 ffmpeg。 分享下如何使用它将各种视频或电影文件,转换成上万张图片数据集、壁纸集合,来让下一篇文章中的模型程序“有米下锅”,这个方法…

Genio 700安卓核心板-MT8390安卓核心板规格参数

Genio 700(MT8390)安卓核心板是一款专门针对智能家居、互动零售、工业和商业应用的高性能边缘人工智能物联网平台。它集成了高度响应的边缘处理、先进的多媒体功能、各种传感器和连接选项,并支持多任务操作系统。 )安卓核心板采用高效的芯片内人工智能多处理器(APU)…

Meta开源支持1000多种语言的文本转语音与语音识别大语言模型

据不完全统计,地球上有超过7000多种语言,而现在的大语言模型仅仅只涉及到了主流的100多种语言。相对全球7000多种语言来讲,这仅仅只是其中的一小部分。如何让全球的人获益,把大语言模型扩展到更多的语言上,一直是大语言模型研究的重点。Meta发布了涵盖 1406 种语言的预训练…

缺陷预测(一)——论文复现

运行CGCN文件 问题一:CNN输入维度的问题出现的问题解决问题原因 问题二:mix时,输入的train_in和train_gen.inputs数据格式不一致出现的问题解决问题 最终结果 问题一:CNN输入维度的问题 出现的问题 数据集改好之后,出…