事物-知晓一二

事物秉性原则:

将事务极可能的缩小。一个事务越大,它存在的风险也就越多。

事物的传播机制可分为:

1.requied 必须地 (Spring默认的传播级别)

如果上下文中存在事物,则加入事物;如果上下文中不存在事物,则新建事物执行。

该级别能满足大多数的业务场景。


2.supports 支持

如果上下文中存在事物,则加入事物;如果上下文中不存在事物,则已非事物状态执行。

所以说,并非所有包在transactionTemplate.execute中的代码都会有事务支持。这个通常是用来处理那些并非原子性的非核心业务逻辑操作。应用场景较少。

场景举例:


3.mandatory 强制地

上下文中必须存在事物,否则抛出异常

作用:有效的控制上下文调用代码遗漏添加事务控制的保证手段

场景举例:比如一段代码不能单独被调用执行,但是一旦被调用,就必须有事务包含的情况,就可以使用这个传播级别。


4.requires_new 新建

从字面即可知道,new,每次都要一个新事务,该传播级别的特点是,每次都会新建一个事务,并且同时将上下文中的事务挂起,执行当前新建事务完成以后,上下文事务恢复再执行。

场景举例:饿了吗下单成功发送红包,在发送之前,要做一些系统的初始化、验证、数据记录操作,然后发送红包,然后再记录发送日志,发送日志要求100%的准确,如果日志不准确,那么整个父事务逻辑需要回滚。

这个举例中,下单是父事物,发红包相当于子事物,不能因为红包发送失败而影响客户的下单操作,发送红包的子事务不会直接影响到父事务的提交和回滚


5.not_suppored 不支持

如果上下文中存在事物,则挂起事物,以非事物状态执行,执行当前逻辑完毕后,恢复上下文中事物。

作用:可以帮助你将事务极可能的缩小。我们知道一个事务越大,它存在的风险也就越多。所以在处理事务的过程中,要保证尽可能的缩小范围。

场景举例:比如一段代码,是每次逻辑操作都必须调用的,比如循环1000次的某个非核心业务逻辑操作。这样的代码如果包在事务中,势必造成事务太大,导致出现一些难以考虑周全的异常情况。所以这个事务这个级别的传播级别就派上用场了。用当前级别的事务模板包起来就可以了。


6.never 从不

该事务更严格,上面一个事务传播级别只是不支持而已,有事务就挂起,而NEVER传播级别要求上下文中不能存在事务,一旦有事务,就抛出runtime异常,强制停止执行!这个级别上辈子跟事务有仇。


7.nested 嵌套

嵌套级别事务。该传播级别特征是,如果上下文中存在事务,则嵌套事务执行,如果不存在事务,则新建事务。

那么什么是嵌套事务呢?很多人都不理解,我看过一些博客,都是有些理解偏差。

嵌套是子事务套在父事务中执行,子事务是父事务的一部分,在进入子事务之前,父事务建立一个回滚点,叫save point,然后执行子事务,这个子事务的执行也算是父事务的一部分,然后子事务执行结束,父事务继续执行。重点就在于那个save point。看几个问题就明了了:

如果子事务回滚,会发生什么?

父事务会回滚到进入子事务前建立的save point,然后尝试其他的事务或者其他的业务逻辑,父事务之前的操作不会受到影响,更不会自动回滚。

如果父事务回滚,会发生什么?

父事务回滚,子事务也会跟着回滚!为什么呢,因为父事务结束之前,子事务是不会提交的,我们说子事务是父事务的一部分,正是这个道理。那么:

事务的提交,是什么情况?

是父事务先提交,然后子事务提交,还是子事务先提交,父事务再提交?答案是第二种情况,还是那句话,子事务是父事务的一部分,由父事务统一提交。

现在你再体会一下这个”嵌套“,是不是有那么点意思?

以上是事务的7个传播级别,在日常应用中,通常可以满足各种业务需求,但是除了传播级别,在读取数据库的过程中,如果两个事务并发执行,那么彼此之间的数据是如何影响的呢?

这就需要了解一下事务的另一个特性:数据隔离级别


数据隔离级别分为不同的四种

1.read uncommitted 读未提交 (最低级别)

2.read commited 读已提交 (oracle默认级别)

一个事物可以读取另一个事物已提交的数据

避免了脏读,仍会出现不可重复读和幻读现象

原因:当我们使用了读已提交的数据级别时,基于锁机制的dbms需要对选中的对象使用写锁直至事物结束,而读锁在select后马上释放,也不要求范围锁,保证了读到的都是已提交,避免读到未提交的数据,保证了数据的正确性。

脏读:事物A修改数据X,事物B读取到了X,此时事物A回滚,事物B就产生了脏读,也就是读取了另一个事物未提交的数据。

3.repeatable read 重复读 (MYSQL默认级别)

保证同一个事物中发出同一个select语句多次,产生数据的结果集相同。

解决了脏读和不可重复读,仍会出现幻读

原因:在可重复读级别中,基于锁机制的DBMS需要对选中的对象的读锁和写锁一直保持到事物结束,但不要求范围锁。

不可重复读:同一个事物发出同一个select,查询结果集不同。

事物A读取数据X,事物B修改了X,事物A再次读X会出现不可重复读。(两次查询结果不同)

4.serializable 串行执行

通过强制事物排序,使之不可能互相冲突,解决了幻读。

原理:在每个读的数据行上加上共享锁。

不足:大量的超时现象和锁竞争。

幻读:当事物A以一定条件查询数据库,查询结果10条,事物B添加了数据库,导致事物A再以相同条件查询时可查出11条。

幻读与不可重复读的区别:

幻读的重点:新增或者删除,相同条件,第一次和第二次读取的数据量不同

不可重复读的重点:修改,相同条件,多次读取数据值不同



 


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值