2021-08-25

  • Post author:
  • Post category:其他




事务的基本原理

Spring事务的本质其实就是数据库对事务的支持,没有数据库的事务支持,spring是无法提供事务功能的。事务是一系列的动作,一旦其中有一个动作出现错误,必须全部回滚,系统将事务中对数据库的所有已完成的操作全部撤消,滚回到事务开始的状态,避免出现由于数据不一致而导致的接下来一系列的错误。事务的出现是为了确保数据的完整性和一致性,在目前企业级应用开发中,事务管理是必不可少的。

事务有四大特性(ACID):1.原子性(Atomicity) 2.一致性(Consistency)3.隔离性(Isolation)4.持久性(Durability)



Spring 事务的传播属性

spring事务的传播属性,就是定义在存在多个事务同时存在的时候,spring应该如何处理这些事务的行为。这些属性在TransactionDefinition中定义,具体常量的解释见下表:

来源:https://www.cnblogs.com/wenbochang/p/13050801.html



spring事务的隔离级别

事务的隔离性,当多个线程都开启事务操作数据库中的数据时,数据库系统要能进行隔离操作,以保证各个线程获取数据的准确性,在介绍数据库提供的各种隔离级别之前,如果不考虑事务的隔离性,多用户访问数据库,就是所谓的事务的并发。可能存在的问题:1.脏读:一个事务读到另一个事务未提交的更新数据。2.不可重复读:一个事务两次读同一行数据,可是这两次读到的数据不一样。3.幻读:一个事务执行两次查询,但第二次查询比第一次查询多出了一些数据行。4.丢失更新:撤消一个事务时,把其它事务已提交的更新的数据覆盖了。

在这里插入图片描述

使用示意:
在这里插入图片描述



事务的嵌套

嵌套是子事务在父事务中执行,子事务是父事务的一部分,在进入子事务之前,父事务建立一个回滚点,叫save point,然后执行子事务,这个子事务的执行也算是父事务的一部分,然后子事务执行结束,父事务继续执行。

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

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

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

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

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

子事务先提交,父事务再提交。子事务是父事务的一部分,由父事务统一提交。



Spring boot事务失效的几种情况

1.内部调用:使用一个没有事务的方法调用一个有事务的方法,失败后不会进行回滚。

2. .没有指定监听的Exception:@Transactional只会监听RuntimeException,当抛出其他异常时,不能正常捕获,也就不会回滚。

解决方法:

手动捕获异常,然后包装为RuntimeException抛出

使用roobackFor属性指定需要捕获的异常

3.内部异常被catch:内部异常被处理try catch处理,并没有抛出异常,异常捕获失败,事务控制不会回滚。

4.方法非public:Transactional注解标注方法修饰符为非public时,@Transactional注解将会不起作用。因为@Transactional 的工作原理是基于AOP来实现的,所以,必须作用在public的方法上才行

5.同一个类中方法调用,导致@Transactional失效:其实这还是由于使用Spring AOP代理造成的,因为只有当事务方法被当前类以外的代码调用时,才会由Spring生成的代理对象来管理

开发中避免不了会对同一个类里面的方法调用,比如有一个类Test,它的一个方法A,A再调用本类的方法B(不论方法B是用public还是private修饰),但方法A没有声明注解事务,而B方法有。则外部调用方法A之后,方法B的事务是不会起作用的。这也是经常犯错误的一个地方

6.数据库不支持事务:如mysql的数据库引擎,innodb支持事务,而myisam就不支持。

7.新开启一个线程:spring实现事务的原理是通过ThreadLocal把数据库连接绑定到当前线程中,新开启一个线程获取到的连接就不是同一个了。



版权声明:本文为weixin_44585469原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。