事务类收集归纳笔记

所归纳的事务有数据库有spring的,归类记录一下,方便查看。

首先什么是事务呢!
简单理解就是同一批操作或则同一个单元任务。内部不管有a,b,c…几个组成。它们要么本次操作都是成功的,要不都是失败。不存在部分情况。

举个例子方便快速理解!

一笔交易中,甲同学给乙同学转钱100块。
甲:减少100
乙:增加100
开启事务,让事务大哥支持一下交易,结果只能有两种!
成功:甲减少100,乙增加100
失败:甲,乙金额不变

了解一下事务的几个特性
1、原子性:如上讲述,结果是不可分割的,要不成功,要不失败。
2、一致性:事务开启前,中,后这些时间点,多个人去看到的数据都是 一样的。比如事务执行中,A看到数据和B看到数据是一样的,不可能在某个时间看到不一样。
3、隔离性:这里所描述的是,每个事务之间是不可干扰的。
4、永久性:意思就是事务提交后,会磁盘记录永久化。

mysql中事务默认是隐式事务,执行insert、update、delete操作的时候,数据库自动开启事务、提交或回滚事务
是否开启隐式事务是由变量autocommit控制的。
所以事务分为隐式事务和显式事务

事务中的一些问题
脏读
一个事务在执行的过程中读取到了其他事务还没有提交的数据。
这个还是比较好理解的。

读已提交
从字面上我们就可以理解,即一个事务操作过程中可以读取到其他事务已经提交的数据。

事务中的每次读取操作,读取到的都是数据库中其他事务已提交的最新的数据(相当于当前读)

可重复读
一个事务操作中对于一个读取操作不管多少次,读取到的结果都是一样的。

幻读
脏读、不可重复读、可重复读、幻读,其中最难理解的是幻读

以mysql为例:

幻读在可重复读的模式下才会出现,其他隔离级别中不会出现
举列子:
幻读现象例子:

可重复读模式下,比如有个用户表,手机号码为主键,有两个事物进行如下操作

事务A操作如下:
1、打开事务
2、查询号码为X的记录,不存在
3、插入号码为X的数据,插入报错(为什么会报错,先向下看)
4、查询号码为X的记录,发现还是不存在(由于是可重复读,所以读取记录X还是不存在的)

事物B操作:在事务A第2步操作时插入了一条X的记录,所以会导致A中第3步插入报错(违反了唯一约束)

上面操作对A来说就像发生了幻觉一样,明明查询X(A中第二步、第四步)不存在,但却无法插入成功

幻读可以这么理解:事务中后面的操作(插入号码X)需要上面的读取操作(查询号码X的记录)提供支持,但读取操作却不能支持下面的操作时产生的错误,就像发生了幻觉一样。

隔离级别分为4种:
读未提交
:READ-UNCOMMITTED

读已提交:READ-COMMITTED

可重复读:REPEATABLE-READ

串行:SERIALIZABLE
在这里插入图片描述

表格中和网上有些不一样,主要是幻读这块,幻读只会在可重复读级别中才会出现,其他级别下不存在

演示摘录
READ-UNCOMMITTED:读未提交

# 隔离级别设置,READ-UNCOMMITTED读未提交,READ-COMMITTED读已提交,REPEATABLE-READ可重复读,SERIALIZABLE串行
transaction-isolation=READ-UNCOMMITTED

重启mysql:

C:\Windows\system32>net stop mysql
mysql 服务正在停止..
mysql 服务已成功停止。

C:\Windows\system32>net start mysql
mysql 服务正在启动 .
mysql 服务已经启动成功

验证执行流程图
在这里插入图片描述
开两个窗口来分别做这两个操作
第一个窗口

mysql> start transaction; Query OK, 0 rows affected (0.00 sec)

mysql> select * from test1; Empty set (0.00 sec)

mysql> select * from test1;
±-----+ | a |
±-----+ | 1 |
±-----+ 1 row in set (0.00 sec)

mysql> commit; Query OK, 0 rows affected (0.00 sec)

第二个窗口

mysql> start transaction; Query OK, 0 rows affected (0.00 sec)

mysql> insert into test1 values (1); Query OK, 1 row affected (0.00
sec)

mysql> select * from test1;
±-----+ | a |
±-----+ | 1 |
±-----+ 1 row in set (0.00 sec)

mysql> commit; Query OK, 0 rows affected (0.00 sec)

这个两检测的结果:
T2-A:无数据,T6-A:有数据,T6时刻B还未提交,此时A已经看到了B插入的数据,说明出现了脏读。

T2-A:无数据,T6-A:有数据,查询到的结果不一样,说明不可重复读
结论:读未提交情况下,可以读取到其他事务还未提交的数据,多次读取结果不一样,出现了脏读、不可重复读

READ-COMMITTED:读已提交
重复上面事务设置工作,
执行流程
在这里插入图片描述

在两个窗口,
T5-B:有数据,T6-A窗口:无数据,A看不到B的数据,说明没有脏读。

T6-A窗口:无数据,T8-A:看到了B插入的数据,此时B已经提交了,A看到了B已提交的数据,说明可以读取到已提交的数据。

T2-A、T6-A:无数据,T8-A:有数据,多次读取结果不一样,说明不可重复读

结论:读已提交情况下,无法读取到其他事务还未提交的数据,可以读取到其他事务已经提交的数据,多次读取结果不一样,未出现脏读,出现了读已提交、不可重复读按照上图的执行流程节点处理。结果如下

REPEATABLE-READ:可重复读
在这里插入图片描述
T2-A、T6-A窗口:无数据,T5-B:有数据,A看不到B的数据,说明没有脏读。

T8-A:无数据,此时B已经提交了,A看不到B已提交的数据,A中3次读的结果一样都是没有数据的,说明可重复读(每次的结果一致)

结论:可重复读的情况下,不会出现脏读,没有读取到其它事务事务提交前后的数据。本身事务所有查询节点数据一致(可重复读)。


幻读演示流程
在这里插入图片描述
开两个窗口演示
第一个

mysql> start transaction; Query OK, 0 rows affected (0.00 sec)

mysql> select * from t_user where name=‘路人甲Java’; Empty set (0.00 sec)

mysql> insert into t_user values (2,‘路人甲Java’); ERROR 1062 (23000):
Duplicate entry ‘路人甲Java’ for key ‘name’ mysql> select * from t_user
where name=‘路人甲Java’; Empty set (0.00 sec)

mysql> commit; Query OK, 0 rows affected (0.00 sec)

第二个

mysql> start transaction; Query OK, 0 rows affected (0.00 sec)

mysql> insert into t_user values (1,‘路人甲Java’); Query OK, 1 row
affected (0.00 sec)

mysql> select * from t_user;
±—±--------------+ | id | name |
±—±--------------+ | 1 | 路人甲Java |
±—±--------------+ 1 row in set (0.00 sec)

mysql> commit; Query OK, 0 rows affected (0.00 sec)

流程节点结果
A想插入数据路人甲Java,插入之前先查询了一下(T5时刻)该用户是否存在,发现不存在,然后在T7时刻执行插入,报错了,报数据已经存在了,因为T6时刻B已经插入了路人甲Java。

然后A有点郁闷,刚才查的时候不存在的,然后A不相信自己的眼睛,又去查一次(T8时刻),发现路人甲Java还是不存在的
明明没有这条记录,但是一插入就提示已存在记录。感觉是自己眼睛看花了一样,产生了幻读。

SERIALIZABLE:串行
在这里插入图片描述
按时间顺序运行上面的命令,会发现T4-B这样会被阻塞,直到T6-A执行完毕。

可以看出来,事务只能串行执行了。串行情况下不存在脏读、不可重复读、幻读的问题了。

--------------隔离级别的选择,在系统中根据业务来做选择-----------------------

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值