spring 事务

tech2022-08-13  118

spring 事务

参考与这位同志

定义: 事务是程序中一系列严密的逻辑操作,可以看做完成某件事情的步骤,这些步骤必须全部成功完成才能完成事务,否则算是执行失败。比如玩英雄联盟,可以看做是上号、寻找游戏、选择英雄等一系列操作(你玩个锤子的游戏,滚去敲代码)。

事务配置方式: spring 支持两种事务配置方式,即编程式事务管理和声明式事务管理。

编程式事务管理: 编程式事务管理是侵入性事务管理,使用 TransactionTemplate 或 PlatformTransactionManager 来声明事务。spring 推荐使用 TransactionTemplate。声明式事务管理: 声明式事务管理是建立在 AOP 之上的。其本质是在方法前后进行拦截,在方法开始前加入或创建一个事务,目标方法执行完成后,根据执行结果提交或者回滚。

注: 编程式事务管理的实现每次都要单独实现,但当业务量大功能复杂时,编程式事务管理就会显得非常复杂。而声明式事务则不同,因为它是非侵入式的,不会影响到业务逻辑层的实现,值需要在配置文件配置事务规则或者通过注解的方式来声明事务,就可以将事务规则应用到业务逻辑中。 声明式事务管理要优于编程式事务管理,这正是 spring 提倡的非侵入式配置方式。唯一的不足之处是声明式事务的粒度是方法级别的,编程式事务的粒度是代码块级别的。不过这种不足可以通过抽取方法的方式来解决。

事务的特性: 事务的四个特性分别是原子性、一致性、隔离性、持久性

原子性: 事务是一系列操作的组合,原子性指的是这些操作要么全部成功执行,要么不执行。一致性: 一致性指的是在事务完成后(不管成功还是失败),事务所处理的数据必须保持一致的状态。隔离性: 隔离性指的是当多个事务同时处理同一个业务时,系统必须保证事务之间相互不影响,以免造成数据损坏。持久性: 持久性指的是当事务完成后,无论发生什么错误,事务的结果不应该受到影响,应该将事务结果持久化。一般是持久化到持久化储存器中。

事务的传播性: 事务的传播性一般出现在事务嵌套的场景。比如一个事务方法中调用了另一个事务方法,那么两个方法是各自独立提交还是内层方法合并到外层当时提交。这就需要事务的传播机制的配置来决定。 事务的传播机制回答了这样一个问题: 一个事务应该被执行还是被挂起,或者说一个方法是否应该在事务性的程序中执行。

Propagation_required: 如果外层有事务,则将当前事务加入外层事务,一同提交,一同回滚。如果外层没有事务,则新建一个事务执行。Propagation_support: 如果外层有事务,则加入外层事务。如果外层没有事务,则以非事务的方式执行。Propagation_required_new: 每次都会开启一个新事务,如果外层有事务则将其挂起,待当前事务执行完成后在执行外层事务。如果外层没有事务则创建一个新事务执行。Propagation_not_support: 不支持事务,如果外层有事务则将其挂起,待当前代码执行完成后再恢复外层事务的执行,无论当前代码执行是否成功都不会发生回滚。Propagation_mandatory: 如果外层没有事务则发生异常。Propagation_never: 如果外层有事务则发生异常。

并发事务所造成的的问题: 并发事务可能会造成数据损坏、错误读取等问题,一般有以下几种:

脏读: 脏读指的是一个事务读取了另一个事务未提交的数据,当另一个事务撤销后,会导致第一个事务读取的数据是无效的。不可重复读: 不可重复读指的是一个事务内进行了两次读取同一行数据却获取到不同结果的问题。这是由于在这两次读取操作中另一个事务对这行数据进行了修改操作。幻读: 幻读指的是一个事务中进行了两次获取大批数据却获取到不同结果的问题。这是由于在这两次读取中另一个事务对这批数据进行了修改或插入的操作。

事务隔离级别: 理论上事务之间是相互隔离的,但这样会影响性能,所以需要根据不同的业务场景来设置事务的隔离级别。

Read_uncommitted: 只读不提交。事务的最低隔离级别,允许一个事务读取另一个事务未提交的数据。上面的三种问题都解决不了。Read_committed: 读并提交。保证了一个事务更新的数据提交后才可被其它事务获取。解决了脏读的问题。Repeatable_read: 重复读。保证了一个事务两次获取到的数据的一致性。解决了脏读和不可重复度的问题。Serilizable: 事务串行序列化,解决了脏读、不可重复度和幻读的问题,完全符合隔离机制,但性能差,因为其完全锁定了事务所涉及到的数据,一般不推荐使用。

回滚规则: 默认情况下,事务只在出现运行异常(runtime exception)时发生回滚,在出现检查异常(checked exception)时不会滚 。但可以声明特定事务,比如声明事务在发生某一个检查异常回滚,声明某一个事务在发生某一个运行异常时不会滚。

事务配置示例:

//事务的传播性配置 @Transaction(propagation = Propagation.REQUIRED) //事务的隔离级别配置 @Transaction(isolation = Isolation = READ_COMMITTED) //只读 @Transaction(readOnly = true) //事务超时设置 @Transaction(timeOut = 30) //事务回滚(异常类可自定义) //指定单一异常类 @Transaction(rollbackFor = RuntimeException.class) //指定多个异常类 @Transaction(rollbackFor = { RuntimeException.class, Exception.class })

《最佳损友》-- 陈奕迅

@

最新回复(0)