@Transactional注解结合mogoDB4.0引发的业务问题(WriteConflict写冲突)

最近在做一个saas项目,该项目用的是springboot+springdata,持久数据层用的是mogoDB。

因为mogoDB4.0新增了多文档事务支持,再加上项目的业务需求,用mogoDB确实是个不错的选择,但是因为mogoDB的事务功能还不够成熟,采用的是全局一致性事务控制,也就是因为这个全局事务控制的特性,在这个项目上引发了非常严重的问题。

我先解释下什么是全局一致性把。

在mogoDB进入了一个事务中的时候,mogoDB会把事务中的数据操作(sql操作)涉及到的数据库(你没有听错,就是整个库)形成一个快照(就是记录这个事务开始时整个库的数据),所以其他事务在这个库中增删改的数据这个事务无法读到

这会引发什么问题?

当我在含有@Transactional注解的业务方法serviceA()去调用另一个业务类中(注意是另一个类,因为@Tanscational注解的特性,不同类处在不同的事务中)含有@Transactional的业务方法serviceB(),而两个serviceA()和serviceB()都修改了同一条数据C(方法A的修改在方法B之前),那么此时mogoDB会报WriteConflict 写冲突的异常。因为serviceB()的事务读取不到serviceA()事务中修改的数据。就算把serviceA()中修改C的操作放在执行serviceB()后面,等serviceB()的事务提交了再在serviceA()里修改C,还是会报WriteConflict 写冲突因为serviceA()事务开始时mogoDB形成了全局一致性快照(4.0特性)。所以不管你把修改C的操作放在serviceA()哪里都是不行的。

如何解决?

目前只找到一种解决方法:
依靠@Tansactional注解的特性,把serviceA()中修改C的操作放到另一个类的方法serviceC()中,然后加上注解

@Transactional(propagation = Propagation.REQUIRES_NEW)

REQUIRES_NEW 这里我就不具体解释了,propagation这个属性是设置事务传播属性,而REQUIRES_NEW是新建一个事务,如果该方法被其他事务方法调用了,则把其他事务挂起,先执行有REQUIRES_NEW的事务。
这时再在serviceA()里调用serviceB()后再去调用serviceC(),修改C就能读到执行serviceB()后的数据了。
但是这样做有一个缺陷,我本来是想要serviceA()回滚后,serviceC()也跟着回滚,但是实际上serviceA()回滚后,serviceC()不会回滚,已经提交了。有取就有舍,唉。

你可能感兴趣的:(工作)