关于MySQL并发问题,还是举个例子来说明。
这里用表类型为innoDB类型
商品库存问题,当库存为0的时候就不能再下单支付了。
demo:
库存商品5件
a下2件,b下1件、c下2件
正常是程序
事务开启
执行程序
回滚
提交
MySql事务分析:
当前有三个用户a、b、c三个用户进入到了这个事务中,这个时候会产生一个共享锁,所以在select的时候,这三个用户查到的库存数量都是5个,同时还要注意,mysql InnoDB查到的结果是有版本控制的,再其他用户更新没有commit之前(也就是没有产生新版本之前),当前用户查到的结果依然是就版本;也就是说在没有commint之前,有新用户购买的数量仍旧是之前的库存量。
然后是update,假如这三个用户同时到达update这里,这个时候update更新语句会把并发串行化,也就是给同时到达这里的是三个用户排个序,一个一个执行,并生成排他锁,在当前这个update语句commit之前,其他用户等待执行,commit后,生成新的版本;这样执行完后,库存肯定为负数了。
所在在执行减库存的时候,我们最好加上条件,库量大于要买的数量。
代码:
//开启事务beginTranse();try{ //$qty为用户购买量 $db->query('UPDATE `ut_product_store` SET `amount`=`amount`-$qty WHERE `amount`>=$qty AND `id`=商品ID');}catch($e Exception){ //回滚 rollBack();}//提交事务commit();