时间:(2023-12-16)
一、 spring的事务传播行为有7种。如下
PROPAGATION_REQUIRED 表示当前方法运行需要事务。如果当前事务存在,方法就会在改事务中运行。否则,会启动一个新的事务。
PROPAGATION_REQUIRED_NEW 表示当前方法必须运行在自己的事务中。方法执行时,一个新的事务将被启动。如果当前存在事务,当前事务会被挂起。
PROPAGATION_SUPPORTS 表示当前方法不需要事务上下文,但是当前如果存在事务,方法将在事务中运行。
PROPAGATION_NOT_SUPPORTED 表示当前方法不能再事务中运行,如果当前存在事务,该方法运行期间事务将被挂起。
PROPAGATION_NEVER 表示当前方法不支持事务,如果当前存在事务,方法执行时会抛出异常。
PROPAGATION_NESTED 表示如果当前存在一个事务,改方法将会在嵌套事务中运行,嵌套的事务可以独立于当前的事务进行提交或回滚。
PROPAGATION_MANDATORY 表示改方法必须在事务中运行,如果当前事务不存在,则会抛出异常。
二、声明式事务
@Transactional(propagation = Propagation.REQUIRED) 可修饰类,方法
Transactional 事务配置标签,propagation 事务传播行为参数 Propagation.REQUIRED具体的事务传播行为。
三、编程式事务
编程式和声明式事务的区别
Spring提供了对编程式事务和声明式事务的支持,编程式事务允许用户在代码中精确定义事务的边界,而声明式事务(基于AOP)有助于用户将操作与事务规则进行解耦。 简单地说,编程式事务侵入到了业务代码里面,但是提供了更加详细的事务管理;而声明式事务由于基于AOP,所以既能起到事务管理的作用,又可以不影响业务代码的具体实现。
四、事务隔离级别
事务隔离级别是有四种,但是spring有5个参数定义。
Isolation 类进行了定义 。
DEFAULT(TransactionDefinition.ISOLATION_DEFAULT), 表示使用后端数据库默认的隔离级别
READ_UNCOMMITTED(TransactionDefinition.ISOLATION_READ_UNCOMMITTED), 读未提交
READ_COMMITTED(TransactionDefinition.ISOLATION_READ_COMMITTED),读已提交
REPEATABLE_READ(TransactionDefinition.ISOLATION_REPEATABLE_READ),可重复读
SERIALIZABLE(TransactionDefinition.ISOLATION_SERIALIZABLE);串行化
不同的事务隔离级别可能引起的问题
可能引发的问题
脏读:事务中读取到其他事务回滚的数据。所谓的脏读,其实就是读到了别的事务回滚前的脏数据。比如事务B执行过程中修改了数据X,在未提交前,事务A读取了X,而事务B却回滚了,这样事务A就形成了脏读。
也就是说,当前事务读到的数据是别的事务想要修改成为的但是没有修改成功的数据。
不可重复读:事务中已经读取到的数据被改变。比如事务A首先读取了一条数据,然后执行逻辑的时候,事务B将这条数据改变了,然后事务A再次读取的时候,发现数据不匹配了,就是所谓的不可重复读了。
也就是说,当前事务先进行了一次数据读取,然后再次读取到的数据是别的事务修改成功的数据,导致两次读取到的数据不匹配,也就照应了不可重复读的语义。
幻读:事务中多次查询结果不一致。比如事务A首先根据条件索引得到N条数据,然后事务B改变了这N条数据之外的M条或者增添了M条符合事务A搜索条件的数据,导致事务A再次搜索发现有N+M条数据了,就产生了幻读。
五、事务的四项原则
ACID
- 原子性( Atomicity )
- 一致性( Consistency )
- 隔离性( Isolation )
- 持续性( Durability )
-
这四个特性简称为 ACID 特性。
(1)原子性。事务是数据库的逻辑工作单位,事务中包含的各操作要么都做,要么都不做
(2)一致性。事务执行的结果必须是使数据库从一个一致性状态变到另一个一致性状态。因此当数据库只包含成功事务提交的结果时,就说数据库处于一致性状态。如果数据库系统 运行中发生故障,有些事务尚未完成就被迫中断,这些未完成事务对数据库所做的修改有一部分已写入物理数据库,这时数据库就处于一种不正确的状态,或者说是 不一致的状态。
(3)隔离性。一个事务的执行不能其它事务干扰。即一个事务内部的操作及使用的数据对其它并发事务是隔离的,并发执行的各个事务之间不能互相干扰。
(4)持续性。也称永久性,指一个事务一旦提交,它对数据库中的数据的改变就应该是永久性的。接下来的其它操作或故障不应该对其执行结果有任何影响。