springboot-seckill
springboot-seckill copied to clipboard
乐观锁有问题,MYSQL事务MVCC并发冲突,获取不到最新version,无论重试多少次,扣库存永远失败
GoodsService.reduceStock()这个方法,外层调用方法是有事务的。 MYSQL默认的事务隔离级别是可重复读。就是在事务中的同一个数据,前后读取值一样不变。就是利用的MVCC多版本控制实现的。 goodsMapper.getVersionByGoodsId(goods.getId())获取最新版本号这个方法由于事务MVCC控制关系,只能查询到小于等于此事务版本的数据。在事务中,查询多少次都获取不到更新的version,无论重试多少次,扣库存永远失败。 改进,应该把重试拿到事务外层来。 我实践测试下来,改动前,50个商品秒杀,消息队列放进来了50个消息,但是成功秒杀只有7个订单。 改进后,50个消息,但是成功秒杀50个订单。