Mysql之事务(下)

Mysql之事务(下)

 

🏝️专栏:Mysql_猫咪-9527的博客-ZEEKLOG博客
🌅主页:猫咪-9527-ZEEKLOG博客 

“欲穷千里目,更上一层楼。会当凌绝顶,一览众山小。”

目录

5. 事务的隔离级别与并发控制

5.1事务的隔离级别

5.2查看与设置事务的隔离级别 

查看全局隔离级别:

查看当前(会话)隔离级别

5.3读未提交(Read Uncommitted)

5.4读提交(Read Committed)

5.5可重复读(Repeatable Read)

5.6串行化(Serializable)

6.多版本并发控制(MVCC) 

 6.1数据库并发的三种场景及MVCC

6.2三个隐藏字段

 6.3undo log

6.4READ VIEW

6.5事务简单流程

7.REPEATABLE READ vs READ COMMITTED

7.1REPEATABLE READ 

 7.2 REPEATABLE READ vs READ COMMITTED

8.常见的名词解释


5. 事务的隔离级别与并发控制

5.1事务的隔离级别
  • 读未提交(Read Uncommitted):可能导致脏读,其他事务未提交的数据会被读取。
  • 读提交(Read Committed):避免脏读,但可能发生不可重复读。
  • 可重复读(Repeatable Read):避免不可重复读,但可能出现幻读。
  • 串行化(Serializable):最严格的隔离级别,强制事务顺序执行,避免幻读,但影响性能。
5.2查看与设置事务的隔离级别 
查看全局隔离级别:
select @@global.tx_isolation;
 查看当前(会话)隔离级别:

 方案一:

select @@tx_isolation

方案二:

select @@session.tx_isolation;

在处理并发事务时,MySQL通过多版本并发控制(MVCC)来避免并发问题。MVCC允许事务读取数据的历史版本而不加锁,从而减少了锁争用,提高了并发性能。

5.3读未提交(Read Uncommitted)
  • 脏读:在读未提交隔离级别下,事务可以读取到其他事务尚未提交的数据。这意味着一个事务可以读取另一个事务修改了但还未提交的数据,这种读取是脏数据,可能会在其他事务回滚时消失。
  • 最低的隔离性:读未提交是所有事务隔离级别中最低的一个,它对数据的隔离性很差,容易引发数据不一致的问题。
  • 不可重复读和幻读:除了脏读外,读未提交还会出现不可重复读和幻读的现象。例如,事务 A 在读取某个数据后,事务 B 修改了这个数据并提交,事务 A 之后再读取相同数据时会得到不同的结果。

5.4读提交(Read Committed)
  • 避免脏读:读提交隔离级别避免了读未提交隔离级别中的脏读问题。即事务只能读取到其他事务已经提交的数据,不能读取到其他事务未提交的数据。因此,避免了一个事务读取到另一个事务正在修改但尚未提交的数据的情况。
  • 不可重复读:虽然读提交避免了脏读,但它仍然可能出现不可重复读的现象。即在一个事务内,读取同一数据的两次结果可能不同,因为其他事务可以在当前事务运行期间对数据进行修改并提交。例如,事务 A 读取数据后,事务 B 修改数据并提交,事务 A 再次读取数据时得到的结果会与第一次不同。
  • 幻读:幻读是指在一个事务内,某个查询的结果集在事务执行过程中发生了变化(即增加或删除了符合条件的行)。由于其他事务可以在事务执行过程中提交数据,读提交隔离级别可能会出现幻读现象。
5.5可重复读(Repeatable Read)
  • 可重复读(Repeatable Read):避免不可重复读,但可能出现幻读。
  • 幻读:事务读取的数据集在事务执行过程中发生变化。例如,事务查询到一定范围内的数据,但在事务执行过程中,其他事务插入了新的数据,导致结果集发生变化。串行化隔离级别能有效防止幻读。

 现象:从你第一次读取开始,到后面事务结束之前你的读取结果都不会放生改变。

开始事务开始事务
select *from account;(快照读)
插入(1,‘张飞’,100)
插入(2,'刘备',111)
commit;
select *from account;(快照读)

开始事务开始事务
插入(1,‘张飞’,100)
插入(2,'刘备',111)
commit;
select *from account;(快照读)

5.6串行化(Serializable)
  • 串行化(Serializable):最严格的隔离级别,强制事务顺序执行,避免幻读,但影响性能

6.多版本并发控制(MVCC) 

 6.1数据库并发的三种场景及MVCC
  • 读-读:不存在任何问题,也不需要并发控制
  • 读-写:有线程安全问题,可能会造成事务隔离性问题,可能遇到脏读,幻读,不可重复读
  • 写-写:有线程安全问题,可能会存在更新丢失问题,比如第一类更新丢失,第二类更新丢失(后面补充)

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

  • 在并发读写数据库时,可以做到在读操作时不用阻塞写操作,写操作也不用阻塞读操作,提高了数据库并发读写的性能
  • 同时还可以解决脏读,幻读,不可重复读等事务隔离问题,但不能解决更新丢失问题
6.2三个隐藏字段
  • DB_TRX_ID :6 byte,最近修改( 修改/插入)事务ID,记录创建这条记录/最后一次修改该记录的事务ID
  • DB_ROLL_PTR : 7 byte,回滚指针,指向这条记录的上一个版本(简单理解成,指向历史版本就行,这些数据一般在undo log 中)
  • DB_ROW_ID : 6 byte,隐含的自增ID(隐藏主键),如果数据表没有主键, InnoDB 会自动以DB_ROW_ID 产生一个聚簇索引

我们查看到的数据库: 

 实际的数据库:

idnameDB_TRX_ID(事务ID)DB_ROW_ID(隐式主键)DB_ROLL_PTR(回滚指针)
1张飞11null

通过事务2将张飞修改为刘备。 

这样的一个个的版本合在一起我们称为快照。 

 6.3undo log

MySQL 中的一段内存缓冲区,用来保存日志数据的。

6.4READ VIEW
class ReadView { // 省略... private: /** 高水位,大于等于这个ID的事务均不可见*/ trx_id_t m_low_limit_id /** 低水位:小于这个ID的事务均可见 */ trx_id_t m_up_limit_id; /** 创建该 Read View 的事务ID*/ trx_id_t m_creator_trx_id; /** 创建视图时的活跃事务id列表*/ ids_t m_ids; /** 配合purge,标识该视图不需要小于m_low_limit_no的UNDO LOG, * 如果其他视图也不需要,则可以删除小于m_low_limit_no的UNDO LOG*/ trx_id_t m_low_limit_no; /** 标记视图是否被关闭*/ bool m_closed; // 省略... };
m_ids; //一张列表,用来维护Read View生成时刻,系统正活跃的事务ID
up_limit_id; //记录m_ids列表中事务ID最小的ID(没有写错)
low_limit_id; //ReadView生成时刻系统尚未分配的下一个事务ID,也就是目前已出现过的事务ID的
最大值+1(也没有写错)
creator_trx_id //创建该ReadView的事务ID 
//判断当前id能否被看到 if(id<m_up_limit_id||id==m_creator_trx_id) return true;//如果比最小的小,则一定能看到,或者就是我本身自己的id if(id>m_low_limit_id) return false;//在我这个事务形成时,这个事务还没有被创建,所以不能被看到 else { //遍历m_ids表,如果不在这个表中 return true; //如果在这个表中就直接 return false; }
6.5事务简单流程
idnameDB_TRX_ID(事务ID)DB_ROW_ID(隐式主键)DB_ROLL_PTR(回滚指针)
1张飞11null

 事务:

 事务四:将张飞修改为刘备

 m_ids; //1   3
up_limit_id; //1
low_limit_id; //5
creator_trx_id //2
//事务2的 Read View

m_ids; //1   3
up_limit_id; //1
low_limit_id; //5     原因:ReadView生成时刻,系统尚未分配的下一个事务ID
creator_trx_id //2

//事务4提交的记录对应的事务ID
DB_TRX_ID=4
//比较步骤
DB_TRX_ID(4)< up_limit_id(1) ? 不小于,下一步
DB_TRX_ID(4)>= low_limit_id(5) ? 不大于,下一步
m_ids.contains(DB_TRX_ID) ? 不包含,说明,事务4不在当前的活跃事务中。

故,事务4的更改,应该看到。
所以事务2能读到的最新数据记录是事务4所提交的版本,而事务4提交的版本也是全局角度上最新的版本

7.REPEATABLE READ vs READ COMMITTED

7.1REPEATABLE READ 

测试表一: 

 测试表二:

  • 用例1与用例2:唯一区别仅仅是表1 的事务B在事务A修改age前快照读过一次age数据
  • 而表2 的事务B在事务A修改age前没有进行过快照读。

结论:

  • 事务中快照读的结果是非常依赖该事务首次出现快照读的地方,即某个事务中首次出现快照读,决定该事务后续快照读结果的能力
  • delete同样如此
 7.2 REPEATABLE READ vs READ COMMITTED
  • 正是Read View生成时机的不同,从而造成RC,RR级别下快照读的结果的不同
  • 在RR级别下的某个事务的对某条记录的第一次快照读会创建一个快照及Read View, 将当前系统活跃的其他事务记录起来 
  • 此后在调用快照读的时候,还是使用的是同一个Read View,所以只要当前事务在其他事务提交更新之前使用过快照读,那么之后的快照读使用的都是同一个Read View,所以对之后的修改不可见;
  • 即RR级别下,快照读生成Read View时,Read View会记录此时所有其他活动事务的快照,这些事务的修改对于当前事务都是不可见的。而早于Read View创建的事务所做的修改均是可见
  • 而在RC级别下的,事务中,每次快照读都会新生成一个快照和Read View, 这就是我们在RC级别下的事务中可以看到别的事务提交的更新的原因
  • 总之在RC隔离级别下,是每个快照读都会生成并获取最新的Read View;而在RR隔离级别下,则是同一个事务中的第一个快照读才会创建Read View, 之后的快照读获取的都是同一个Read View。
  • 正是RC每次快照读,都会形成Read View,所以,RC才会有不可重复读问题。

8.常见的名词解释

脏读:一个事务读取到另一个事务未提交的数据。由于另一个事务尚未提交,它所做的修改可能会被回滚,从而导致第一个事务读取到的数据是无效的或不一致的。
不可重复读:在一个事务中,多次读取同一条记录时,得到的结果不同
可重复读:在一个事务中,多次读取同一条记录时,得到的结果相同
幻读:事务在多次执行相同查询条件的情况下,第二次查询发现之前不存在的记录突然“出现”了,或者之前存在的记录“消失”了。这种现象通常发生在 INSERTDELETE 操作时。

Read more

备战蓝桥杯----C/C++组 (一)所需C++基础知识(上)

备战蓝桥杯----C/C++组 (一)所需C++基础知识(上)

个人主页: wengqidaifeng ✨永远在路上,永远向前走 个人专栏: 数据结构 C语言 嵌入式小白启动! 重要OJ算法题详解 文章目录 * 前言 * 一. 分析大纲,了解所需 * 1. 大纲显示内容 * 2、组别划分与难度关系 * 3、知识点结构分析(按组别) * 3.1 大学C组:基础入门阶段 * 3.2 大学B组:中级提高阶段 * 3.3 大学A组 / 研究生组:高级挑战阶段 * 4.难度系数说明 * 二. C++基础语法(上):从零开始的编程基石 * 1.前言 * 2.开发环境搭建 - DevC++的安装与使用 * 2.1

By Ne0inhk
【C++贪心】P8769 [蓝桥杯 2021 国 C] 巧克力|普及+

【C++贪心】P8769 [蓝桥杯 2021 国 C] 巧克力|普及+

本文涉及知识点 C++贪心 [蓝桥杯 2021 国 C] 巧克力 题目描述 小蓝很喜欢吃巧克力,他每天都要吃一块巧克力。 一天小蓝到超市想买一些巧克力。超市的货架上有很多种巧克力,每种巧克力有自己的价格、数量和剩余的保质期天数,小蓝只吃没过保质期的巧克力,请问小蓝最少花多少钱能买到让自己吃 x x x 天的巧克力。 输入格式 输入的第一行包含两个整数 x x x, n n n,分别表示需要吃巧克力的天数和巧克力的种类数。 接下来 n n n 行描述货架上的巧克力,其中第 i i i 行包含三个整数 a i a_i ai , b i b_i bi

By Ne0inhk
C++测试与调试:确保代码质量与稳定性

C++测试与调试:确保代码质量与稳定性

C++测试与调试:确保代码质量与稳定性 一、学习目标与重点 本章将深入探讨C++测试与调试的核心知识,帮助你确保代码的质量与稳定性。通过学习,你将能够: 1. 理解测试与调试的基本概念,掌握测试方法和工具 2. 学会使用单元测试框架,如Google Test和Catch2 3. 理解集成测试的重要性,确保系统的功能正确性 4. 学会使用调试工具,如GDB和Visual Studio调试器 5. 培养测试与调试思维,设计高质量的代码 二、测试的基本概念 2.1 测试的分类 测试可以分为以下几类: * 单元测试:测试单个函数或类的功能 * 集成测试:测试多个模块的集成功能 * 系统测试:测试整个系统的功能 * 验收测试:测试系统是否满足用户需求 * 性能测试:测试系统的性能指标 2.2 测试原则 测试应该遵循以下原则: * 测试应该尽可能早地进行 * 测试应该覆盖所有可能的场景 * 测试应该是自动化的

By Ne0inhk