【JavaWeb】71:事务的四大特性以及隔离级别

​今天是刘小爱自学Java的第71天。

感谢你的观看,谢谢你。

话不多说,继续数据库事务的学习:

昨天写了一个银行转账的案例,通过该案例引出了对于数据库事务这个概念的学习。

但是在代码编写过程中我发现了一个问题。

一、对于事务回滚的疑惑

怎么感觉事务的回滚可有可无的样子?

这是我昨天接触到事务这个概念后的一个感触。

当然毕竟才刚开始接触事务,所以我给自己留了条后路,说明自己学识有限,肯定有忽视的地方,还得多多学习。

至于我为什么会产生这样的疑惑?是源于我对代码进行了修改测试。其中代码如下:

①开启事务

将事务设置成手动提交。

②转出账户

用户A给用户B转账,用户A账户余额减少。

③自己创造一个异常

用这段代码来模拟有异常和没有异常。

④转入账户

用户B收到了用户A的转账,其账户余额增加。

如果将③中的异常注释掉,那么代码没有异常,顺利执行,事务提交,数据库对应数据发生改变。

⑤如果发生了异常

也就是利用③来制造异常,事务回滚,回到事务开启时的状态。

但是现在问题来了:

我将⑤中的事务回滚代码删除掉,③中有异常,执行代码发现数据库中的数据并没有改变。

因为出现了异常,事务提交的代码也没有执行到,那么事务没有提交,就算没有回滚,对结局并没有什么改变。

既然如此,那怎么感觉事务回滚可有可无的样子?

昨天我在每天的学习打卡中提出了自己的疑惑,也有很多小伙伴给出了回答:

①②③没有理解我想表达的意思,大部分都是像这样尝试给我说明事务回滚的作用以及重要性。

但这不是我的问题,看来是我没有将疑惑表达清楚,果然学会提问题也是一名程序员应该具备的能力。

所以我仔细捋了捋我的思路,提出疑问:

事务不提交和事务回滚就结果而言是一样的?那么回滚的作用是啥?它们的区别又是什么?

而④和⑤解决了我对其的困惑。

事务开启后,想要结束事务,要么提交,要么回滚,不然资源都被占用了。

就相当于开启了一个线程,用完后不主动关闭,它就会一直运行着占用资源,直到程序本身结束。

资源占用,是这个问题的核心关键,也是我昨天完全没想到的一个问题。

而⑥中提出了一个问题:没有提交是怎么实现数据回到事务开始之前的呢?

也就是事务不提交和事务回滚的区别?

这个问题经过今天的学习,在我心中也有了答案:

1.事务提交,才会对数据库本身数据产生修改。

2.事务开启后,对于数据库的修改可以将其理解成是存放在临时库上面的。(脏读就是读取了临时库上的数据)

3.事务回滚,就相当于取消了这个临时库,对数据库中的实际数据并未影响。

4.事务不提交,和事务回滚一样的效果,但是回滚是即时生效的,而不提交会持续到连接结束才会实现回滚。以上便是我对昨天疑惑的反思以及找寻到的答案。,接下来开始新知识点的学习。

二、事务的特性 ACID

emm……这一块都是概念性的知识点,学起来很枯燥,但是面试可能会被问到,不知道还不行。

①原子性(Atomicity)

为何叫它原子?

因为原子是化学反应不可再分的基本微粒,是化学中最小的存在,事务中的操作是不可分割的。也就是说事务中的操作是一个整体,要么全部成功,要么全部失败。

不能这几个操作成功,另外几个操作失败(这就是在分割事务了)。

②一致性(Consistency)

这个是什么意思呢?

用转账的案例来理解就是:用户A和用户B一共一万块钱,他们之间不管转账多少次,转账多少钱,事务结束后,这两个用户的钱加起来还是一万块。

这就是事务的一致性,就有点类似于能量守恒原则。

③持久性:(Durability)

事务成功提交之后,对于数据库的改变是永久的

哪怕数据库发生异常,重启之后数据亦然存在。

④隔离性(Isolation)

比如说在操作同一张表时,数据库为每个用户开启的事务,不能被其他事务的操作所干扰,多个并发事务之间要相互隔离。

三、事务的隔离级别

安全级别越低,效率越高,但是不安全,从安全级别由低到高逐个说明:

1.安全级别最低(read uncommitter)

在这种级别下就会出现一个问题,脏读。

什么叫脏读?

一个事务读取到另一个事务未提交的数据,也就是一开始说的临时库中的数据

显而易见,这种情况极其不安全的,是不被允许的。

①设置隔离级别

set session transaction isolation level read uncommitted;

read uncommitted,翻译就是读未提交的数据,非常地好理解。

②开启事务A

修改了数据库中的数据,但是还未提交事务,也就是说数据库的数据还未改变。

③开启事务B

在隔离级别最低的情况下。

事务B能够读取到事务A中还未提交的数据。

④用现实里发消息作为理解

2安全级别:read committed

read committed,读已提交的数据。

在这个安全级别下,不会发生脏读的问题,但是又会出现不可重复读的问题。

什么叫不可重复读

通俗地理解就是:

数据更新,事务提交,数据库数据被修改,读取到了一些数据。

数据再次更新,事务提交,数据库数据被修改,再次读取时读取到的数据不一样了。

那这不是很正常么?没有问题呀。

但是在某种特定的情况下是有问题的。

一般情况下是没问题的,Oracle默认就是这种级别。

3安全级别:repeatable read

可重复读,在一个事务中读到的数据始终保持一致,无论另一个事务是否提交。

也就是哪怕数据库里的数据发生修改了,读取到的还是以前读到的数据。

①设置可重复读级别

set session transaction isolation level repeatable read;

MySQL数据库默认就是这种级别。

②事务A

A中修改了数据,并提交,那么数据库中本身的数据发生了变化。

③事务B

因为事务B设置了可重复读级别,所以就算数据库中的数据发生了多少变化,读取的数据都是一致的。

当然如果提交了事务再查询,读取到的数据就是变化后的数据了。

④财务报表实例说明

但是其又会出现一个问题,就是幻读。

什么叫幻读呢?

一个事务在前后两次查询同一范围的时候,后一次查询看到了前一次查询没有看到的行。

说白了就是读取到的数据突然多了一个或多个(被另外的事务进行了增加操作),仿佛出现了幻觉一般,所以就叫幻读 。

其中,幻读在MySQL中被优化掉了,也就是说不会出现幻读的问题,所以也没法演示看看幻读到底是个什么回事。

4安全级别:serializableml

serializableml,可串行化的意思。

串行化锁定了整张表,所以幻读不存在的。

怎么可以理解可串行化呢?就是相当于将事务像羊肉串一样串起来了。

所以一次只能执行一个事务,没法并发执行事务了

这种情况下是最安全的,但是效率也就最低了。

最后

谢谢你的观看。

如果可以的话,麻烦帮忙点个赞,谢谢你。

猜你喜欢

转载自blog.csdn.net/qq_41228864/article/details/106966166