在我们的电商系统中,有一个表存放商品的总量iNum1和已经购买量iNum2(或者剩余量)。
当用户购买了一个商品,我们后台的业务逻辑原来是这样处理的:
根据ID获取商品对像
Product product = commonService.getProductById(productId);
根据对象得到剩余量
buiedNum = product.getNum2();
剩余量加1
buiedNum--;
然后更新数据到新的剩余量
update table set iNum2=buiedNum。
在单用户操作的情况下这样没有问题,如果是多用户并发,第一个用户获取到剩余量和第二个用户获取到的剩余量是一样的(数据库事务采用默认模式),假设都是100,那么2个用户操作之后,新的剩余量都是99,数据库里面的剩余量会更新为99.导致有一个用户的购买行为没有记录到剩余量里面。商品中记录的数据和实际卖出的数据不一致,导致商品会有超卖的情况。
因此,在多用户并发的情况下不能把剩余量、已卖出量等数字作为中间数据存起来进行数学运算。
而直接采用在sql里面进行数字运算,以上例,最终更新数据的sql为:
update table set iNum2=iNum2-1 where id=XXX and iNum2>0
如果执行的影响结果为0,则表示已经超卖,事务回滚。