编程随笔-SpringBoot | 07. 事务Transaction

0.事务的基本概念

事务ACID理解

一般说到事务,一定会有ACID四个特点:

  • 原子性(Atomicity)
  • 一致性(Consistency)
  • 隔离性(Isolation)
  • 持久性(Durability)

1.事务的四个特性

1.1.原子性(Atomicity)

事务操作要么同时成功,要么同时失败

这里写图片描述

如上图事务(A转账给B 200元)包含两个过程:

A:800 - 200 = 600(元)

B:200 + 200 = 400(元)

这两个过程在一个事务中,必须同时成功或同时失败,不能只发生其中一个动作

1.2.一致性(Consistency)

事务前后数据完整性必须一致(数据仍然正确有效)

这里写图片描述

步骤同上,一致性要求这两个步骤符合逻辑,数据正确

1.3.隔离性(Isolation)

多个用户并发访问数据库时,数据库应为每一个用户单独开启事务

多个并发事务之间要相互隔离,不能被其他事务的操作干扰

若这两个事务同时进行,那么就会出现问题:

  • 脏读:一个事务读取了另一个事务尚未提交的数据
  • 不可重复读:一个事务涉及多次读取,在此过程中有另一事务改变了其中数据
  • 幻读(虚读):一个事务涉及多次读取,在此过程中有另一事务插入新的数据

这三个概念将在下面讲解

1.4.持久性(Durability)

事务一旦提交,对数据库的操作就是永久的

2.为什么需要隔离性

事务级别,不可重复读和幻读的区别

如果事务之间不是相互隔离,可能会出现以下的问题:

2.1.脏读

一个事务读取了另一事务尚未提交的数据

临时处理而尚未提交的数据,我们认为它是“脏”的

假设A与C同时向B转账:

这里写图片描述

事务一:A向B转账200元

事务二:C向B转账100元

image-20210530151639456

正确数据“脏读”导致的数据
A800 - 200 = 600(元)800 - 200 = 600(元)
B200 + 100 + 200 = 500(元)200 + 100 = 300(元)
C1000 - 100 = 900(元)1000 - 100 = 900(元)

2.2.不可重复读(针对某一条记录:update和delete)

一个事务涉及多次读取,在此过程中有另一事务改变了其中数据

仍然假设A与C同时向B转账

这里写图片描述

事务一:B多次查询自己的余额(查询一条记录)

事务二:A向B转账200元

事务三:C向B转账100元

则可能会出现以下的执行状况:

事务一(B查询余额)事务二(A向B转账200元)事务三(C向B转账100元)
1开启事务一
2开启事务二
3开启事务三
4查询余额:200元
5A向B转账200元
6提交事务
7查询余额:400元
8C向B转账100元
9提交事务
10查询余额:500元

事务一在执行的过程中,因为事务二和事务三的干扰,多次查询出的余额都不一致,这就是不可重复读

2.3.幻读(针对多条记录:insert)

一个事务涉及多次读取,在此过程中有另一事务插入新的数据

仍然假设A与C同时向B转账

这里写图片描述

事务一:B多次查询自己今日的所有交易记录(查询多条记录)

事务二:A向B转账200元

事务三:C向B转账100元

则可能会出现以下的执行状况:

事务一(B查询记录)事务二(A向B转账200元)事务三(C向B转账100元)
1开启事务一
2开启事务二
3开启事务三
4查询记录:0条
5A向B转账200元
6提交事务
7查询记录:1条
8C向B转账100元
9查询记录:1条
10提交事务
11查询记录:2条

事务一在执行时,事务二和事务三有插入新的数据,导致事务一在多次查询的结果行数都有所不同,这就是幻读

3.事务的隔离级别

先说说提交:

只有insert(增),delete(删),update(改)才涉及提交

select(查)不涉及提交

3.1.默认 - Default

  • Oracle:读已提交(二级隔离:Read committed)
  • Mysql:可重复读(三级隔离:Repeatable read)

3.2.读未提交 - Read uncommitted

最低级的隔离级别,事务可以读取另一事务未提交的数据

可能出现脏读、不可重复读和幻读

事务一(B反复查询余额)事务二(A向B转账)
1事务开启
2事务开启
3查询余额:200
4A向B转账2000元
5查询余额:2200(脏读
6A撤销转账,修改转账额为200元
7查询余额:400
8提交事务
9查询余额:400

3.3.读已提交 - Read committed

二级隔离,只读取已提交的数据,未提交则不读

有效避免脏读,但无法解决不可重复读和幻读

3.4.可重复读 - Repeatable read(MySQL默认

三级隔离,当事务A开启,则不允许其他事务对事务A占用的数据进行修改

实现原理是事务A对第一次读取到的数据上行锁

事务一(B反复查询余额)事务二(A向B转账200元)
1事务开启
2事务开启
3查询余额:200元
4A尝试向B转账200元,但因上锁被拒绝
报出异常,事务终止/回滚
5查询余额:200元

这里事务是终止/回滚,可以在service层中捕获异常,发生异常时递归,就能实现事务二等待事务一完成后再执行

有效避免脏读、不可重复读,但仍可insert,因此无法避免幻读

3.5.串行化 - Serializable

最高级隔离,读取时加“读锁”,写入时加“写锁”,一般是上范围锁

如果出现读写锁冲突,则后开启事务必须等待先开启事务全部执行完毕方可执行:

读写锁冲突有三种情况:

  • 事务A读取数据加“读锁”,事务B尝试写入数据,此时 读 - 写冲突
  • 事务A写入数据加“写锁”,事务B尝试读取数据,此时 写 - 读冲突
  • 事务A写入数据加“写锁”,事务B尝试写入数据,此时 写 - 写冲突

事务100%隔离,避免脏读、不可重复读和幻读,但代价太大,通常不用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值