赞
踩
批量写入场景里要不要启用事物,其实很多人都有自己的看法,这里我给出启用于不启用的利弊,
假如在批量写入过程中发生网络波动或者数据库宕机,我们其实只需要重新新建一条通知消息,然后重新操作即可。
因为上一条通知消息因为批量插入步骤没有全部完成,所以推送状态是失败。后续等开发人员处理一下脏数据即可。
@Transactional
是 Spring
框架提供得事务注解,相信这是许多人都知道的,但是在一些高性能场景下,是不建议使用的,推荐通过编程式事务来手动控制事务提交或者回滚,减少事务影响范围,因而提升性能。
采用 @Transactional
事务注解
- @Transactional(rollbackFor = Exception.class)
- public void doUnPaidTask(Long orderId) {
- // 1. 查询订单是否存在
- Order order = orderService.getById(orderId);
- ,,,
-
- // 2. 更新订单为已取消状态
- order.setOrderStatus((byte) OrderStatusEnum.ORDER_CLOSED_BY_EXPIRED.getOrderStatus());
- orderService.updateById(order);
- ...
- // 3. 订单商品数量增加
- LambdaQueryWrapper<OrderItem> queryWrapper = Wrappers.lambdaQuery();
- queryWrapper.eq(OrderItem::getOrderId, orderId);
- List<OrderItem> orderItems = orderItemService.list(queryWrapper);
- for (OrderItem orderItem : orderItems) {
- Long goodsId = orderItem.getGoodsId();
- Integer goodsCount = orderItem.getGoodsCount();
- if (!goodsDao.addStock(goodsId, goodsCount)) {
- throw new BusinessException("秒杀商品货品库存增加失败");
- }
- }
-
- // 4. 返还用户优惠券
- couponService.releaseCoupon(orderId);
- log.info("---------------订单orderId:{},未支付超时取消成功", orderId);
- }
可以看到上面订单回滚的代码逻辑有四个步骤,如下,
这里面有个问题,订单回滚方法里面其实只有 2、3、4 步骤是需要在一个事物里执行的,第 1 步其实可以放在事物外面来执行,以此缩小事物范围。
使用编程式事务对其优化后,代码如下
- @Resource
- private PlatformTransactionManager platformTransactionManager;
- @Resource
- private TransactionDefinition transactionDefinition;
-
- public void doUnPaidTask(Long orderId) {
- // 启用编程式事务
- // 1. 在开启事务钱查询订单是否存在
- Order order = orderService.getById(orderId);
- ...
- // 2. 开启事务
- TransactionStatus transaction = platformTransactionManager.getTransaction(transactionDefinition);
- try {
- // 3. 设置订单为已取消状态
- order.setOrderStatus((byte) OrderStatusEnum.ORDER_CLOSED_BY_EXPIRED.getOrderStatus());
- orderService.updateById(order);
- ...
- // 4. 商品货品数量增加
- LambdaQueryWrapper<OrderItem> queryWrapper = Wrappers.lambdaQuery();
- queryWrapper.eq(OrderItem::getOrderId, orderId);
- List<OrderItem> orderItems = orderItemService.list(queryWrapper);
- for (OrderItem orderItem : orderItems) {
- Long goodsId = orderItem.getGoodsId();
- Integer goodsCount = orderItem.getGoodsCount();
- if (!goodsDao.addStock(goodsId, goodsCount)) {
- throw new BusinessException("秒杀商品货品库存增加失败");
- }
- }
-
- // 5. 返还优惠券
- couponService.releaseCoupon(orderId);
- // 6. 所有更新操作完成后,提交事务
- platformTransactionManager.commit(transaction);
- log.info("---------------订单orderId:{},未支付超时取消成功", orderId);
- } catch (Exception e) {
- log.info("---------------订单orderId:{},未支付超时取消失败", orderId, e);
- // 7. 发生异常,回滚事务
- platformTransactionManager.rollback(transaction);
- }
- }
可以看到采用编程式事务后,我们将查询逻辑排除在事务之外,这样也就减小了事物影响范围。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。