在分布式系统中,事务的传播行为(Transaction Propagation)指的是在不同的事务上下文中如何处理事务的传播方式。它决定了一个方法在执行时是否应该在当前事务中运行,是否应该创建新的事务,或者是否应该加入到已有的事务中。事务传播行为在多层架构的系统(例如 Spring 框架中)尤为重要。
常见的事务传播行为类型
以下是 Spring 框架中的七种常用事务传播行为,这些传播行为可以应用于服务层或业务逻辑中不同方法之间的事务控制。
1. PROPAGATION_REQUIRED
(默认)
- 描述:
如果当前没有事务,创建一个新的事务。如果已经存在事务,加入到当前事务中。 行为:
- 如果方法内没有事务,则会创建一个新的事务。
- 如果方法内已有事务,则会加入到当前事务。
- 使用场景:
大部分情况下使用此传播行为,因为它允许方法在已有事务的上下文中执行,或者为没有事务的操作创建新的事务。 - 举例:
如果一个方法调用了另一个方法,而另一个方法也有事务,两个方法将会共享同一个事务。
2. PROPAGATION_REQUIRES_NEW
- 描述:
总是创建一个新的事务。如果当前有事务存在,则会挂起当前事务,并启动一个新的事务。 行为:
- 如果方法内已有事务,它会先挂起该事务,创建一个新的事务。
- 当前事务完成后,新的事务提交或回滚。
- 使用场景:
用于那些不希望被现有事务影响的操作,例如需要确保某些操作总是成功的,而不会因为外部事务失败而回滚。 - 举例:
假设有一个方法A,它调用了方法B,方法B使用PROPAGATION_REQUIRES_NEW
,那么方法B的事务会独立于方法A的事务执行。即使方法A回滚,方法B也会提交。
3. PROPAGATION_SUPPORTS
- 描述:
如果当前有事务,方法将在当前事务中运行。如果没有事务,方法将以非事务的方式运行。 行为:
- 如果已有事务,方法会加入到当前事务中。
- 如果没有事务,方法将不会创建新的事务,也不参与任何事务。
- 使用场景:
用于那些可以选择性地参与事务的操作,例如某些读取操作,可以在没有事务的情况下执行。 - 举例:
一个方法执行读取操作时,不需要强制事务,但如果外部调用者已经有事务,它会加入该事务。
4. PROPAGATION_NOT_SUPPORTED
- 描述:
总是以非事务的方式执行,如果当前存在事务,则会挂起当前事务。 行为:
- 当前方法不支持事务,若当前有事务,则挂起事务,执行时不在事务上下文中运行。
- 使用场景:
用于那些不希望在事务内执行的操作,例如某些不需要事务控制的操作。 - 举例:
如果方法需要执行某些不希望参与事务的操作(例如某些批量操作),可以选择PROPAGATION_NOT_SUPPORTED
。
5. PROPAGATION_NEVER
- 描述:
如果当前存在事务,则抛出异常。该方法不支持事务。 行为:
- 如果方法内已有事务,抛出异常。
- 如果没有事务,则方法会正常执行。
- 使用场景:
用于那些不能在事务内执行的操作,若存在事务则需要抛出异常。 - 举例:
某些操作可能不希望在事务内进行,如涉及到外部系统的调用,或者某些特定的系统行为。
6. PROPAGATION_MANDATORY
- 描述:
必须在一个现有事务中执行,如果当前没有事务,则抛出异常。 行为:
- 如果方法没有事务,则抛出异常。
- 如果已有事务,方法将加入到现有事务中。
- 使用场景:
用于要求事务必须存在的场景,如果当前没有事务,调用者会收到异常。 - 举例:
如果方法必须在事务上下文中执行(例如某些金融系统操作),可以使用此传播行为。
7. PROPAGATION_IDLE
- 描述:
此行为是一个比较特殊的选项,表示如果当前没有事务,则不会创建新的事务;但如果当前有事务,则它会与当前事务共享。 行为:
- 如果没有事务,它不会创建新的事务。
- 如果有事务,则它会加入到现有事务中。
传播行为与事务隔离级别的关系
在分布式系统中,事务传播行为与事务隔离级别密切相关。隔离级别定义了一个事务能够看见其他事务的修改的程度,而传播行为则定义了如何在事务之间传递执行上下文。
- 传播行为决定了如何启动、加入或挂起事务。
- 隔离级别决定了事务之间的执行顺序和它们对其他事务的可见性。
Spring 事务传播行为总结表
传播行为 | 如果当前存在事务 | 如果当前不存在事务 |
---|---|---|
PROPAGATION_REQUIRED | 加入当前事务 | 创建一个新的事务 |
PROPAGATION_REQUIRES_NEW | 挂起当前事务,创建新事务 | 创建一个新的事务 |
PROPAGATION_SUPPORTS | 加入当前事务 | 非事务性执行 |
PROPAGATION_NOT_SUPPORTED | 挂起当前事务,非事务性执行 | 非事务性执行 |
PROPAGATION_NEVER | 抛出异常 | 非事务性执行 |
PROPAGATION_MANDATORY | 加入当前事务 | 抛出异常 |
总结
事务传播行为是分布式系统中至关重要的一部分,它决定了多个方法和事务之间如何交互。选择合适的事务传播行为能够帮助确保系统的一致性、可靠性和性能。在实际开发中,通常会根据不同的业务需求和数据一致性要求来决定使用哪种传播行为。例如,如果你希望某些方法总是加入现有事务中,则可以选择 PROPAGATION_REQUIRED
;如果某些操作必须独立运行,则可以选择 PROPAGATION_REQUIRES_NEW
。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。