baomidou / dynamic-datasource

dynamic datasource for springboot 多数据源 动态数据源 主从分离 读写分离 分布式事务
https://www.kancloud.cn/tracy5546/dynamic-datasource/2264611
Apache License 2.0
4.75k stars 1.19k forks source link

@DS要生效,必须得@transactional(propagation = Propagation.REQUIRES_NEW)吗? #580

Closed edwardlzh closed 1 year ago

edwardlzh commented 1 year ago

Please fill it out carefully, or it will be closed. 请认真填写,不然会直接关闭。

Enviroment

JDK Version(required): 1.8.0_131

SpringBoot Version(required): 2.7.12

dynamic-datasource-spring-boot-starter Version(required):3.5.2

druid Version(optional):

Describe what happened

Expected Result: 希望serviceB回滚,并且serviceB的@DS能生效

Actual Result: serviceB的@DS生效了,但是事务是独立的

Steps to reproduce

@ds("sla1") @transactional(propagation = Propagation.REQUIRES_NEW) serviceB.xx();

@transactional serviceC.xx(); }

请问,有什么好的解决办法吗?

ZPZP1 commented 1 year ago

你这种相当于开启了两个事务,Spring事务中是不能切换数据源的,可以用多数据源提供的@DsTransactional

edwardlzh commented 1 year ago

spring事务中不是可以依靠org.springframework.transaction.annotation.Transactional#transactionManager切换事务管理器吗?当然我意思是不使用@DS的情况下,通过注册多个数据源和配套的TransactionManager,然后在嵌套的service调用中切换事务管理器。 @ZPZP1

ZPZP1 commented 1 year ago

可以注册多个事务管理器,以DataSourceTransactionManager为例会判断你当前线程是否存在持有链接作为判断是否事务存在的依据,你要每个事务管理器自己实现是否存在事务的判断逻辑,和事务处理的具体逻辑,这是很难控制而且很容易有问题,如果你非要这样做,可以试试

edwardlzh commented 1 year ago

实际上,我的意思是如果我不用@DS注解,伪代码:

@Transactional serviceA{

@Transactional(transactionManager = "firstTransactionManager")
serviceB.xx();

@Transactional(transactionManager = "secondTransactionManager")
serviceC.xx();

}

两个事务管理器分别对应两个数据源,这个代码,不会出现表不存在的问题,并且确实是一个事务控制了两个数据源连接。 同时,如果serviceB的传播机制为request_new,也是没有问题的。这种写法,虽然配置起来比较麻烦,比如配置多个事务管理器。但是不会像@DS那样与@Transactional冲突。而且,@DSTransactional虽然能解决@DS数据源切换的问题,但是我认为它舍弃了原生@Transactional的事务传播机制,好像也不太合适吧?

@ZPZP1

huayanYu commented 1 year ago

@edwardlzh 选择你认为对的方式去做