spring 事物传播特性和隔离级别

一、Propagation (事务的传播属性)

Propagation :  key属性确定代理应该给哪个方法增加事务行为。这样的属性最重要的部份是传播行为。有以下选项可供使用:PROPAGATION_REQUIRED--支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。
PROPAGATION_SUPPORTS--支持当前事务,如果当前没有事务,就以非事务方式执行。
PROPAGATION_MANDATORY--支持当前事务,如果当前没有事务,就抛出异常。
PROPAGATION_REQUIRES_NEW--新建事务,如果当前存在事务,把当前事务挂起。
PROPAGATION_NOT_SUPPORTED--以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
PROPAGATION_NEVER--以非事务方式执行,如果当前存在事务,则抛出异常。

1: PROPAGATION_REQUIRED
加入当前正要执行的事务不在另外一个事务里,那么就起一个新的事务
比如说,ServiceB.methodB的事务级别定义为PROPAGATION_REQUIRED, 那么由于执行ServiceA.methodA的时候,
ServiceA.methodA已经起了事务,这时调用ServiceB.methodB,ServiceB.methodB看到自己已经运行在ServiceA.methodA
的事务内部,就不再起新的事务。而假如ServiceA.methodA运行的时候发现自己没有在事务中,他就会为自己分配一个事务。
这样,在ServiceA.methodA或者在ServiceB.methodB内的任何地方出现异常,事务都会被回滚。即使ServiceB.methodB的事务已经被
提交,但是ServiceA.methodA在接下来fail要回滚,ServiceB.methodB也要回滚

2: PROPAGATION_SUPPORTS
如果当前在事务中,即以事务的形式运行,如果当前不再一个事务中,那么就以非事务的形式运行


3: PROPAGATION_MANDATORY
必须在一个事务中运行。也就是说,他只能被一个父事务调用。否则,他就要抛出异常

4: PROPAGATION_REQUIRES_NEW
这个就比较绕口了。 比如我们设计ServiceA.methodA的事务级别为PROPAGATION_REQUIRED,ServiceB.methodB的事务级别为PROPAGATION_REQUIRES_NEW,
那么当执行到ServiceB.methodB的时候,ServiceA.methodA所在的事务就会挂起,ServiceB.methodB会起一个新的事务,等待ServiceB.methodB的事务完成以后,
他才继续执行。他与PROPAGATION_REQUIRED 的事务区别在于事务的回滚程度了。因为ServiceB.methodB是新起一个事务,那么就是存在
两个不同的事务。如果ServiceB.methodB已经提交,那么ServiceA.methodA失败回滚,ServiceB.methodB是不会回滚的。如果ServiceB.methodB失败回滚,
如果他抛出的异常被ServiceA.methodA捕获,ServiceA.methodA事务仍然可能提交。

5: PROPAGATION_NOT_SUPPORTED
当前不支持事务。比如ServiceA.methodA的事务级别是PROPAGATION_REQUIRED ,而ServiceB.methodB的事务级别是PROPAGATION_NOT_SUPPORTED ,
那么当执行到ServiceB.methodB时,ServiceA.methodA的事务挂起,而他以非事务的状态运行完,再继续ServiceA.methodA的事务。

6: PROPAGATION_NEVER
不能在事务中运行。假设ServiceA.methodA的事务级别是PROPAGATION_REQUIRED, 而ServiceB.methodB的事务级别是PROPAGATION_NEVER ,
那么ServiceB.methodB就要抛出异常了。

7: PROPAGATION_NESTED
理解Nested的关键是savepoint。他与PROPAGATION_REQUIRES_NEW的区别是,PROPAGATION_REQUIRES_NEW另起一个事务,将会与他的父事务相互独立,
而Nested的事务和他的父事务是相依的,他的提交是要等和他的父事务一块提交的。也就是说,如果父事务最后回滚,他也要回滚的。
而Nested事务的好处是他有一个savepoint。
*****************************************
ServiceA {

/**
* 事务属性配置为 PROPAGATION_REQUIRED
*/
void methodA() {
try {
//savepoint
ServiceB.methodB(); //PROPAGATION_NESTED 级别
} catch (SomeException) {
// 执行其他业务, 如 ServiceC.methodC();
}
}

}
********************************************
也就是说ServiceB.methodB失败回滚,那么ServiceA.methodA也会回滚到savepoint点上,ServiceA.methodA可以选择另外一个分支,比如
ServiceC.methodC,继续执行,来尝试完成自己的事务。
但是这个事务并没有在EJB标准中定义。

Spring事务的隔离级别
 1. ISOLATION_DEFAULT: 这是一个PlatfromTransactionManager默认的隔离级别,使用数据库默认的事务隔离级别.
      另外四个与JDBC的隔离级别相对应
 2. ISOLATION_READ_UNCOMMITTED: 这是事务最低的隔离级别,它充许令外一个事务可以看到这个事务未提交的数据。
      这种隔离级别会产生脏读,不可重复读和幻像读。
 3. ISOLATION_READ_COMMITTED: 保证一个事务修改的数据提交后才能被另外一个事务读取。另外一个事务不能读取该事务未提交的数据
 4. ISOLATION_REPEATABLE_READ: 这种事务隔离级别可以防止脏读,不可重复读。但是可能出现幻像读。
      它除了保证一个事务不能读取另一个事务未提交的数据外,还保证了避免下面的情况产生(不可重复读)。
 5. ISOLATION_SERIALIZABLE 这是花费最高代价但是最可靠的事务隔离级别。事务被处理为顺序执行。
      除了防止脏读,不可重复读外,还避免了幻像读。

什么是脏数据,脏读,不可重复读,幻觉读?
 脏读: 指当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没有提交到数据库中,这时,
     另外一个事务也访问这个数据,然后使用了这个数据。因为这个数据是还没有提交的数据, 那么另外一
     个事务读到的这个数据是脏数据,依据脏数据所做的操作可能是不正确的。
    
 不可重复读: 指在一个事务内,多次读同一数据。在这个事务还没有结束时,另外一个事务也访问该同一数据。
             那么,在第一个事务中的两次读数据之间,由于第二个事务的修改,那么第一个事务两次读到的数据
             可能是不一样的。这样就发生了在一个事务内两次读到的数据是不一样的,因此称为是不可重复读。
            
 幻觉读: 指当事务不是独立执行时发生的一种现象,例如第一个事务对一个表中的数据进行了修改,这种修改涉及
         到表中的全部数据行。同时,第二个事务也修改这个表中的数据,这种修改是向表中插入一行新数据。那么,
         以后就会发生操作第一个事务的用户发现表中还有没有修改的数据行,就好象发生了幻觉一样。

 

 

另附

表 9.1. <tx:method/> 有关的设置

属性是否需要?默认值描述
name 与事务属性关联的方法名。通配符(*)可以用来指定一批关联到相同的事务属性的方法。 如:'get*'、'handle*'、'on*Event'等等。
propagationREQUIRED事务传播行为
isolationDEFAULT事务隔离级别
timeout-1事务超时的时间(以秒为单位)
read-onlyfalse事务是否只读?
rollback-for 将被触发进行回滚的 Exception(s);以逗号分开。 如:'com.foo.MyBusinessException,ServletException'
no-rollback-for 不 被触发进行回滚的 Exception(s);以逗号分开。 如:'com.foo.MyBusinessException
<think>首先,用户的问题是:“我想了解Spring框架中事务的传播机制有哪些 请问Spring事务传播机制类型有哪些”。这直接询问Spring事务传播机制的类型。 根据系统级指令: - 所有行内数学表达式必须使用 $...$ 格式,但在这个上下文中,可能没有数学表达式,所以我可以忽略。 - 独立公式必须使用 $$...$$ 格式并单独成段,同样,可能不适用。 - LaTeX语法正确。 - 使用中文回答。 - 生成相关问题。 - 回答中引用的段落末尾自然地添加引用标识,例如 [^1]。 - 回答结构清晰,帮助用户逐步解决问题,尽量保证回答真实可靠。 用户提供了几个引用: - 引用[1]:提到Spring的事务传播机制,包括事务特性传播机制类型如REQUIRED、SUPPORTS等。 - 引用[2]:解释Spring事务传播机制基于AOP事务管理器实现。 - 引用[3]:提到Spring通过@Transactional注解支持声明式事务,传播行为是关键参数。 - 引用[4]:详细描述了传播机制类型,特别是NESTED,并举例说明。 - 引用[5]:给出一个@Transactional注解的例子,包括propagation参数。 我需要基于这些引用构建回答。用户的问题是询问传播机制的类型,所以我应该列出并解释常见的传播机制类型。 常见的Spring事务传播机制类型包括: 1. REQUIRED 2. SUPPORTS 3. MANDATORY 4. REQUIRES_NEW 5. NOT_SUPPORTED 6. NEVER 7. NESTED 这些在引用[1][4]中明确提到。 我的回答结构应该清晰: - 先简要介绍什么是事务传播机制。 - 然后列出并解释每个类型。 - 最后生成相关问题。 使用中文回答。 添加引用:在解释时,自然地添加引用标识。例如,当提到某个类型时,引用相关来源。 生成相关问题:在回答末尾添加“相关问题”部分,就像示例中那样。 逐步回答: 1. 介绍事务传播机制:简要解释什么是传播机制,基于引用[2][3]。 2. 列出类型:基于引用[1][4]。 - REQUIRED:如果当前有事务,加入它;否则,新建事务。 - SUPPORTS:如果当前有事务,加入它;否则,非事务执行。 - MANDATORY:如果当前有事务,加入它;否则,抛出异常。 - REQUIRES_NEW:挂起当前事务,新建一个事务。 - NOT_SUPPORTED:挂起当前事务,非事务执行。 - NEVER:非事务执行;如果当前有事务,抛出异常。 - NESTED:如果当前有事务,创建一个嵌套事务;否则,新建事务。 3. 解释每个类型时,参考引用[4]的例子。 4. 添加引用标识:例如,在描述后添加 [^1] 或 [^4]。 生成相关问题: - 类似示例,如: 1. 如何选择合适的传播机制? 2. Spring事务传播机制的实现原理是什么? 3. NESTED传播机制的具体应用场景? 确保回答真实可靠:基于提供的引用,不添加额外信息,除非必要。 最终回答结构: - 开头:介绍传播机制。 - 主体:列出每个类型并解释。 - 结尾:相关问题。</think>### Spring事务传播机制类型介绍 在Spring框架中,事务传播机制定义了当一个事务方法调用另一个事务方法时,事务如何传播或处理。这是基于AOP(面向切面编程)事务管理器(如DataSourceTransactionManager)实现的[^2]。通过@Transactional注解,开发者可以指定传播行为,这是声明式事务管理的关键参数之一[^3]。Spring提供了7种标准的事务传播机制类型,每种类型适用于不同的场景。下面我将逐一解释这些类型,确保内容清晰可靠。 #### 事务传播机制类型 1. **REQUIRED** 如果当前存在活动事务,则加入该事务;如果不存在,则新建一个事务。这是最常用的传播机制,适用于大多数业务场景。例如,在服务调用链中,确保所有操作在同一个事务中执行[^1][^4]。 2. **SUPPORTS** 如果当前存在活动事务,则加入该事务;如果不存在,则以非事务方式执行。适用于查询操作或不需要严格事务保证的场景[^1][^3]。 3. **MANDATORY** 如果当前存在活动事务,则加入该事务;如果不存在,则抛出异常。这强制要求方法必须在事务上下文中调用,常用于确保数据一致性[^1][^4]。 4. **REQUIRES_NEW** 挂起当前事务(如果存在),并新建一个独立的事务。新事务提交或回滚不影响原始事务。适用于需要隔离操作的场景,如日志记录或外部服务调用[^1][^4]。 5. **NOT_SUPPORTED** 挂起当前事务(如果存在),并以非事务方式执行。适用于不需要事务支持的操作,例如只读任务或性能敏感场景[^1][^3]。 6. **NEVER** 以非事务方式执行;如果当前存在活动事务,则抛出异常。这确保方法不会被事务上下文干扰,常用于纯查询方法[^1][^4]。 7. **NESTED** 如果当前存在活动事务,则创建一个嵌套事务(作为子事务);如果不存在,则新建一个事务。嵌套事务可以独立回滚,但不影响父事务提交。使用场景示例: - 如果ServiceA(传播机制REQUIRED)调用ServiceB(传播机制NESTED),当ServiceA异常时,整个事务回滚(包括ServiceB)。 - 如果ServiceB异常,ServiceA可以捕获异常后正常提交,而ServiceB单独回滚[^4]。 这适用于需要部分回滚的复杂业务逻辑。 #### 使用示例 在代码中,可以通过@Transactional注解指定传播机制类型,例如: ```java @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.READ_COMMITTED) public void exampleMethod() { // 业务逻辑 } ``` 这里,propagation参数定义了传播行为,其他参数如isolation(隔离级别)可结合使用[^5]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值