美文网首页
一个神奇的事务控制代码

一个神奇的事务控制代码

作者: 进击的三文鱼 | 来源:发表于2021-05-16 17:29 被阅读0次

一 前言
事务,是一个很大的概念,程序员通过操控事务来保证数据的一致性,可是也是经常被忽略的一个点,为什么呢,因为功能的开发者,经常是单向的开发,就是不考虑异常的发生,这也是为什么很多人不喜欢写异常处理,同样事务本身是一个补偿机制,是一个出现问题后才会有用的技术。
二 故事背景
乐乐在做功能时发现了这样一段代码,而且上面有一段神奇的注释
/**

  • 此方法不能加事务,否则会导致save的数据还会提交到数据库时finish中产生的event在消费时找不到对应的记录
  • @param trans
  • @param operator
    */
    public void recharge(Transaction trans, String operator) {
    trans = this.tradeService.save(trans);
    this.tradeService.finish(trans, trans.getBankName(), trans.getTradeSerialNo(), operator);
    }

@Transactional(rollbackFor = Throwable.class)
public Transaction finish(Transaction trans, String bankName, String string, String operator) {
trans.setBankName(bankName);
trans.setReceiveString(string);
trans.setStatus(Transaction.Status.Success.value());
trans.audit(operator);
//扣款成功时间
trans.setDeductionDoneTime(new Date());
trans = save(trans);
return this.notify(trans);
}

public Transaction notify(Transaction trade) {
logger.info("发起调用结算通知:{},TransactionId:{} 生成事件",trade.getPaymentRef(),trade.getNotifyId());
this.bus.asyncPost(new JmsMessages.AfterTradeCallback(trade.getNotifyId()));
return trade;
}
复制代码
代码是从上到下的调用方式,首先上面写了一个注释不能加事务,是不是很奇怪,然后我们发现一个表被save了两次,一番思考后看出了端倪,是因为如果对第一个方法加了事务,那么整个调用链就都在一个事务里面,而抛出事件后是在另外一个线程中处理数据,这样同步的情况下,上一个事务其实没有提交,就导致后面的事件线程无法获取到上一个事务中插入数据库的数据,其实这段代码在不开启同步时是没错的,因为异步处理,上一个事务会提交,事件进行读取数据时就可以读取到了。

相关文章

网友评论

      本文标题:一个神奇的事务控制代码

      本文链接:https://www.haomeiwen.com/subject/nxjrjltx.html