Spring事务的传播行为
1. 概述
当我们遇到下面的情况时,一个service中调用了另一个service中的方法(两个service中都存在事务),此时bservice中的事务就被传播到了aservice中,这样就产生了事务的传播。
@Sercice
public class Aservice{
@AutoWired
private Bservice bservice;
public void order(){
yyyy();
bservice.xxxx();
zzzz();
}
}
因为两个service都存在事务,那么生成的sql语句可能如下
BEGIN
update yyyy;
-------两个事务的分割线------
BEGIN
updata xxxx;
COMMIT;
---------------------------
update zzzz;
COMMIT;
很显然,上面的mysql语句是不支持的。
那么这里就存在一个问题,在mysql中,当第二个begin执行时,会隐式的将第一个事务直接提交了,从而导致aservice中的z
zzz()
方法最终会以一个无事务的状态去运行。
所以,当【B事务】传播到【A事务中】时,【B事务】要做一下微调,而微调的结果可以分为以下几种情况。
(1)当Aservice中有事务
1. 融入事务
第一种情况,Bservice中的事务融入Aservice中的事务(融入A事务),这种场景是最多的
BEGIN
update yyyy;
-------两个事务的分割线------
updata xxxx; # B事务融入到A事务中
---------------------------
update zzzz;
COMMIT;
2. 挂起事务
第二种情况,挂起【A事务】,让【B事务】独立于【A事务】去运行。
当两个事务需要各自独立维护自身事务, 单个事务则无法独立完成,【B事务】启动时可以先给【A事务】暂时挂起,就是阻塞住不给【A事务】继续发送sql,从而让【A事务】无法去提交,B开启一个新的事务,B执行完成后,【A事务】继续。
(1)当Aservice中无事务
1. 以事务的方式运行
第一种情况: 【B事务】以事务的方式运行
select yyyy;
-------两个事务的分割线------
BEGIN
updata xxxx;
COMMIT;
---------------------------
select zzzz;
2. 以无事务的方式运行
第一种情况: 【B事务】以无事务的方式运行
select yyyy;
-------两个事务的分割线------
select xxxx;
---------------------------
select zzzz;
3. 嵌套事务
BEGIN
update yyyy;
--两个事务的分割线(模拟伪事务)--
SAVEPOINT a;
updata xxxx;
ROLLBACK TO a;
---------------------------
update zzzz;
COMMIT;
嵌套过程如下:
- 内部
SAVEPOINT a
的代码如果有问题,则直接回滚至保存点。- 整个事务的提交也不受内部事务(伪事务)的影响。
2. 传播事务
@Transactional(propagation =
下面的值
)
- Propagation.REQUIRED:表示当前方法必须运行在事务中,如果外界有事务存在,方法就会在外界事务中运行,否则,就会启动一个新的事务。REQUIRED就是需要,意思就是B无论如何要有事务。
- Propagation.SUPPORTS: 表示当前方法不需要事务上下文,如果外界存在事务的话,那么该方法就在外界的事务中运行,否则执行该方法时也不需要事务。
- Propagation.MANDATORY: (强制性的),表示该方法必须在事务中运行,如果外界事务不存在,就会抛出一个
IllegalTransactionStateException
异常。 - Propagation.REQUIRES_NEW: (需要个新的),表示当前方法必须运行在自己的事务中,一个新的事务将被启动,如果外部事务存在,在该方法运行期间,外部事务将会被挂起。
- Propagation.NOT_SUPPORTED: (不支持事务),表示当前方法不应该运行在事务中,如果存在外部事务,那么在该方法运行期间,会将外部事务挂起,独立的去以非事务的方式去运行当前方法,当前方法运行结束后,再唤醒外部事务。
- Propagation.NEVER: (不运行在有事务的环境中), 表示当前方法不应该运行在事务的上下文当中,如果该方法外部存在事务,就会抛出
IllegalTransactionStateException
异常。 - Propagation.NESTED:(嵌套的) 表示如果存在外部事务,那么该方法将会在外部事务嵌套自己的事务去运行。嵌套的事务可以独立于外部事务进行单独的提交或者回滚,如果外部事务不存在,那么当前方法会自己创造一个事务,在自己创造的事务中运行。
标签:事务,Spring,zzzz,传播,yyyy,Propagation,方法,运行 From: https://www.cnblogs.com/lunyasen/p/17995659/spring-shi-wu-de-chuan-bo-xing-wei注意: 不同的数据库语言对这种嵌套事务的支持是有所差异的。有的支持,有的不支持。