背景:需要全量更新数据,先删除再插入,插入失败则回滚删除操作,所以把两个数据库操作放在统一事务中。理论上来说,是很简单的事情,但是耗费了两天半的时间解决。
问题:插入失败,删除操作并未回滚。排查常见的事务不生效原因,均没有问题。如:
- 事务注解只能在public方法上才会生效
- 同一个类中方法间调用会导致事务不生效,A调用B,A没有事务,B有事务,AB处于同一个类ClassA中,则导致B的事务不生效。解决方法有:
- 在ClassA类中注入自己,通过ClassA.B()进行调用
- 新建一个类ClassB,将B方法放入ClassB中,在ClassA中注入ClassB,进行调用
- 异常被try-catch住
- 类没有被Spring管理,比如忘记加@Service注解
- 数据库表不支持事务,比如用了MyISAM,需要查看数据库表使用的引擎类型。
- 没有开启事务管理器,但如果使用springboot会自动开启。并不需要特殊配置。
脑袋疼....根本找不到问题原因啊,甚至都debug到源码上了,看到也是进了事务的。
后来定位到是事务管理器的问题,查看数据库数据源配置,clickhouse的数据库显式配置了事务管理器。
@Bean(name = "clusterTransactionManager")
public DataSourceTransactionManager masterTransactionManager() {
retur