liuyangming / ByteTCC

ByteTCC is a distributed transaction manager based on the TCC(Try/Confirm/Cancel) mechanism. It’s compatible with the JTA specification. User guide: https://github.com/liuyangming/ByteTCC/wiki
https://www.bytesoft.org/
GNU Lesser General Public License v3.0
2.9k stars 911 forks source link

单服务,多个数据源事务问题。try抛出异常,cancel没有执行 #117

Open lj865074284 opened 4 years ago

lj865074284 commented 4 years ago

单服务(spring boot的项目,版本0.5.7),多个数据源的业务。 下面是我的代码 `@Service("tccTestTryImpl") @Compensable( interfaceClass = TccTestService.class, confirmableKey = "tccTestConfirmImpl", cancellableKey = "tccTestCancelImpl" ) public class TccTestTryImpl implements TccTestService { @Autowired private TestMapper testMapper;

@Autowired
@Qualifier("tccAceshiTryImpl")
private TccAceshiService tccAceshiService;

@Override
@Transactional(value = "primaryTransactionManager")
public void test() {
    testMapper.addMessage("分布式事务tcc主库插入成功");
    System.out.println("分布式事务tcc主库插入成功");

    tccAceshiService.test();

    throw new NullPointerException();
}

} `

`@Service("tccAceshiTryImpl") @Compensable( interfaceClass = TccAceshiService.class, confirmableKey = "tccAceshiConfirmImpl", cancellableKey = "tccAceshiCancelImpl" ) public class TccAceshiTryImpl implements TccAceshiService { @Autowired private AAceshiMapper aAceshiMapper;

@Override
@Transactional(value = "secondaryTransactionManager", propagation = Propagation.REQUIRES_NEW)
public void test() {
    aAceshiMapper.addMessage("分布式事务tcc从库插入成功");
    System.out.println("分布式事务tcc从库插入成功");
}

} ` confirm和cancel别的代码就不贴了,抛出一个异常,但是ceshi和test的cancel业务代码根本没有走。 并且及时不抛异常,confirm业务代码也没有执行。 是我的配置不对吗?

liuyangming commented 4 years ago

首先, 你在TccTestTryImpl类中抛出异常,该逻辑是不会被cancel的,因为本地事务直接就回滚了,无需cancel了,这一点在用户指南中有详细介绍; 其次,TccAceshiTryImpl类定义的事务传播级别为REQUIRES_NEW,因此它与TccTestTryImpl不在一个全局事务中,TccTestTryImpl的异常不会导致它的回滚,按理它的confirm会被执行,如果没有执行,请检查配置是否正确(即它参与的可能是本地事务而非全局事务)。 第三、TccAceshiTryImpl与TccTestTryImpl,事务管理器还不一样?确定是用的byteTCC的事务管理器么?如果是,使用一个即可,没必要配置两个;如果不是,请检查配置是否正确。尽量参考byteTCC-sample的配置样例。

lijiawei199 commented 2 years ago

首先, 你在TccTestTryImpl类中抛出异常,该逻辑是不会被cancel的,因为本地事务直接就回滚了,无需cancel了,这一点在用户指南中有详细介绍;

想问一下作者 bytetcc是以什么做为依据来判断本地事务回滚无需cancel的呢。

lijiawei199 commented 2 years ago

是自己调用自己本地事务的情况下不需要调用cancel吗? 那是不是可以理解为这个cancel实现类是不是这种调用链路就不会被用到 只有当前服务被其他服务调用并且失败的时候才可能需要用到cancel实现类?

liuyangming commented 2 years ago

首先, 你在TccTestTryImpl类中抛出异常,该逻辑是不会被cancel的,因为本地事务直接就回滚了,无需cancel了,这一点在用户指南中有详细介绍;

想问一下作者 bytetcc是以什么做为依据来判断本地事务回滚无需cancel的呢。

byteTCC记录了每一个service所归属的本地事务,该本地事务的commit/rollback操作实际上也是由spring容器委托给byteTCC来执行的。因此,byteTCC在commit/rollback该本地事务时,就可以将该本地事务涉及的service设置为完成(不必执行cancel)了。