场景:
在分布式多台服务的情况下,有两个请求同时调用AB接口,AB接口有一个共同的D方法,AB方法加了事务且加了锁,D方法也加了事务和锁,D方法的使用场景是用来控制一个活动的参与次数(即数据库的条数),假如次数为200,D方法会先查询数据库条数是否大于等于200,如果条件成立则拦截掉,不成立则进行insert操作
产生的问题:
AB接口共同请求D方法的时候,假如A先请求到D方法,上锁-处理逻辑-释放锁,A方法的事务还未提交,B方法马上调用到D 同样的操作上锁-处理逻辑-释放锁,由于A方法的事务还没提交,导致B方法的查询条数不一致的情况
产生问题的原因:
事务未提交导致,查询的数据是未提交之前的
临时解决问题的办法:
最开始是想到个临时解决方案,就是用redis记录条数,这样就不用理会事务是否提交;
最终解决问题的办法:
使用编程式事务控制D方法,释放锁之前将事务commit, 注意编程式事务不要搭配@Transactional注解一起使用,否则会无效;
编程式事务的使用方法:
1、
声明
@Autowired
private DataSourceTransactionManager dataSourceTransactionManager;
@Autowired
private TransactionDefinition transactionDefinition;
2、方法中引用,获取事务的状态
TransactionStatus transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition);
3、提交事务
dataSourceTransactionManager.commit(transactionStatus);
4、防止出现异常,所以在try中加上回滚代码
dataSourceTransactionManager.rollback(transactionStatus);