深入理解Mysql(七):msyql事务

一.绪论

前面的六篇文章中,已经给大家深入讲解了MySQLbuffer pool机制、redo log机制和undo log机制,相信大家现在对我们平时执行一些增删改语句的实现原理,都有了一定较为深入的理解了,接下来我会讲解mysql的事务,会站在mysql内核角度,进一步深入理解事务

二.事务

2.1事务的由来

事务的根本原因在于多线程操作

我们操作数据库的时候,一个事务可能会有多条数据,当事务A在执行的时候,事务B也可能在执行,这个时候由于多线程操作数据库,就会引发一些问题,比如在前面我讲解了buffer pool,redolog,undolog几个机制,就会有一些问题

1.多个事务并发执行时候,可能会对同一个缓存页的一行数据进行更新,怎么处理这个冲突?

2.一个事物在对数据处理时候,另外一个事物在查询这行数据,怎么办?

2.2 事务带来的四种问题

如图所示,当多个事务同时对数据库进行crud时候,会产生事物的四种情况

1.脏写

2.脏读

3.不可重复读

4.幻读

下面依次来介绍这四种情况

2.2.1 脏写

脏写是指两个事务对同一个数据进行修改,事务A把它改为A,事务B把它改为B,并且事务B提交了,随后事务A回滚了,导致事务B的更新被覆盖

这种已经不满足事务的基本条件,事务提交后,数据就不会改变,所以脏写是所有数据库都不能允许发生的情况

2.2.2 脏读

脏读是指一个事务读到另外一个未提交的事务修改的值,当修改值的事务回顾时候,导致数据的不一致.

如上图,事务A修改数据为A,事务B这个时候读取的值就是A,此时事务A回滚了, 原始数据的值是xxx,但是此时事务B读取的确是A,导致数据的不一致;

脏写和脏读的本质是一个事务能获取到另外一个事物没有提交的数据,因为另外一个事物并没有提交,所以他随时可以回滚,一旦回滚,就会导致脏写/脏读问题

2.2.3 不可重复读

脏读和脏写是读一个事物未提交的数据,会导致的问题,后面两种不可重复读和幻读的前提是读取别人已经提交的事务,如下图所示:

1.事务B读取数据是xxx

2.事务A修改数据为A

3.事务B再次读取,数据变成了A

同一个事物B读取了多次,但是数据确实不一样的,这是✅还是❎呢?


事务B第一次读取是xxx,第二次读取是A,说正确也算正确,毕竟这个时候事务A已经提交了,事务B多次查询事务提交后的值,也没问题;


说有问题也算有问题,就是希望一个事务从开始到结束,查询的数据希望永远是一个值,希望这条数据是可以重复读的,所以可重复度是否有问题,取决于你想要数据库这么办

2.2.3 幻读

幻读是指事物中用同样的sql查询多次,查询的数据条数不一样

比如select * from users where id >10;

第一次查询出10条,然后另外一个事物查询一条数据,再次执行这个sql,发现查出来11条;

就像是幻觉一样,所以叫做幻读!!😄

2.3 事务的隔离级别

数据库在多线程执行的时候,会导致脏写,脏读,不可重复度,幻读问题,所以sql标准中就规定了事务的几种隔离,用来解决这些问题

注意,隔离级别是sql的标准,是针对所有数据库的,比如oracle,不是单单指mysql,sql标准中规定四种隔离级别,分别是
1.read uncommitted(读未提交),

2.read committed(读已提交),

3.repeatable read(可重复读),

4.serializable(串行化)

这几中都比较简单,就不做过多赘述,简单讲解

2.3.1 读未提交

这种隔离级别下,能避免脏写,不能避免脏读,不可重复读和幻读,一般来说系统开发中,没人会把隔离级别设置成这个最低的级别

2.3.2 读已提交

这种隔离级别下,能读取到别的事务已经提交的数据,能避免脏写,脏读,不能避免不可重复读和幻读, oracle的默认的隔离级别就是这种

2.3.3 可重复度

这种级别下,不会发生脏写,脏读,和不可重复读的问题,事务中多次读取一条数据,这条数据的值不会发生变化,但是还是会发生幻读情况

2.3.4 序列化

这种级别杜绝所有情况,因为这种情况是不允许多线程操作的,所有的线程必须排队,一个一个的执行,这就大大降低数据库的并发能力,除非脑子瓦特掉了,不然没人会这样搞的


总结 读未提交和序列化,在实际中不会有人这样设置的,重点关注就是RC和RR

2.4 sping 注解事务

如果想要测试mysql的事务,需要设置myslq的事务级别

SET [GLOBAL|SESSION] TRANSACTION ISOLATION LEVEL level;

LEVEL level 可以设置为REPEATABLE READ,READ COMMITTED,READ UNCOMMITTED,SERIALIZABLE四种

另外再开发中,spring开启事务也是可以设置的

@Transactional(isolation=Isolation.DEFAULT) 你也可以设置为

@Transactional(isolation.READ_UNCOMMITTED) 读未提交的事务,但是一般不建议你这样搞,让别的开发知道因为你瞎改事务隔离级别而引起问题,估计后面会被打死的😭😭😭😭

三.msyql如何解决事务带来的问题

mysql的隔离级别是RR,但是它却能完美决绝脏读,不可重复读和幻读问题,mysql可是花费不小心思,用的正是MVCC(多版本并发控制),在讲解这个MVCC之前,首先先介绍下 undo log版本链

3.1 undo log版本链

mysql中的每条数据,其实都有两个隐藏的字段,一个是trx_id(事务id),一个是 roll_pointer,

trx_id 是最近一次更新这个数据的事务id

roll_pointer 就是指向更新这个事务之前生成的undo log

如图所示

事务A插入一条数据,这个时候在undolog 中roll_point为空,事务id=50;

事务B修改这条数据为B,事务id=51,roll_point指向 txr_id=50的那条数据, 同理当事务C执行后,在undo log中会形成一个版本链

3.2 mvcc

相关推荐
Asthenia04122 小时前
浏览器缓存机制深度解析:电商场景下的性能优化实践
后端
专注API从业者3 小时前
分布式电商系统中的API网关架构设计
大数据·数据仓库·分布式·架构
databook4 小时前
『Python底层原理』--Python对象系统探秘
后端·python
超爱吃士力架5 小时前
MySQL 中的回表是什么?
java·后端·面试
uhakadotcom5 小时前
Google DeepMind最近发布了SigLIP 2
人工智能·算法·架构
追逐时光者5 小时前
Plotly.NET 一个为 .NET 打造的强大开源交互式图表库
后端·.net
苏三说技术6 小时前
10亿数据,如何迁移?
后端
bobz9656 小时前
openvpn 显示已经建立,但是 ping 不通
后端
customer087 小时前
【开源免费】基于SpringBoot+Vue.JS个人博客系统(JAVA毕业设计)
java·vue.js·spring boot·后端·开源
qq_459238497 小时前
SpringBoot整合Redis和Redision锁
spring boot·redis·后端