mysql锁研究系列四(事务在并发情况下避免超卖)

原创 2015年08月24日 19:14:35

我们在做电商的时候会考虑到一个问题,如果此时库存就剩一个,而来了两个并发同时下单,如何避免库存超卖?
先贴一段代码:

    beginTranse(开启事务)
    $sql = "select * from goods where title='测试商品'";
    $tmp = $db->query($sql);
    $info= $db->fetch_assoc($tmp);

    $time = time();
    if($info['stock']>0)
    {

        $sql = "insert into test_order(name,price,create_time) values('{$info['title']}','{$info['price']}','{$time}')";
        $db->query($sql);

        $sql = "update goods set stock = stock -1 where title='测试商品'";
        $db->query($sql);
    }
    commit(提交事务);

这段代码很简单 先查看库存,然后判断有库存就下单操作。
那么这样的情况会出现超卖吗?利用上节学到的知识分析:

  1. 两个事务同时读取同一个商品,inndb对select语句不会加锁,就算加共享锁,其他事务也可以读。所以两个事务得到的库存都是1
  2. 两个事务同时修改操作,mysql会将并发update语句串行化处理,一个一个执行。这样当第一个update操作的时候会生成排他锁,其他事务等待,当第一个事务提交后,第二个事务得到锁继续update操作。那这样的话库存就为-1了。

    上面的代码看似逻辑正常,其实会出现超卖,其实我们只要改一下sql语句就搞定了,在update下判断库存:

$sql = "update goods set stock = stock -1 where title='测试商品' and stock>0";

由于mysql的排他锁保持事务的原子性,update操作也是原子性。按照上面的逻辑走下来的时候:当第一个事务提交后,这行数据已经改变,而第二个事务update时候判断已经为0 了,就不会执行update操作!

关于高并发情况:例如秒杀、抢购之类的情况。mysql是没法支撑的。因为频繁的读写一行会造成锁等待和死锁,而这些所等待进程挂起是相当占mysql资源的。当然不排除像阿里这样的公司 将mysql源码修改,关闭死锁,在引擎层做队列,而且可以合并提交,例如对一行数据的100个update stock-1 语句 合并起来一条语句 update stock -100 。这些都涉及到底层修改。我们肯定没法考虑。其他关于秒杀的实现,这里不做探讨。网上的说法很多,原理差不多,但其实真正遇见时才会发现问题。

版权声明:本文为博主原创文章,未经博主允许不得转载。

mysql处理高并发,防止库存超卖

今天王总又给我们上了一课,其实mysql处理高并发,防止库存超卖的问题,在去年的时候,王总已经提过;但是很可惜,即使当时大家都听懂了,但是在现实开发中,还是没这方面的意识。今天就我的一些理解,整理一下...
  • caomiao2006
  • caomiao2006
  • 2014年08月14日 23:44
  • 57080

如何解决秒杀的性能问题和超卖的讨论

最近业务试水电商,接了一个秒杀的活。之前经常看到淘宝的同行们讨论秒杀,讨论电商,这次终于轮到我们自己理论结合实际一次了。   ps:进入正文前先说一点个人感受,之前看淘宝的ppt感觉都懂了,等到自己...
  • zhoudaxia
  • zhoudaxia
  • 2014年09月22日 23:38
  • 28011

Mysql在高并发情况下,防止库存超卖而小于0的解决方案

背景: 本人上次做申领campaign的PHP后台时,因为项目上线后某些时段同时申领的人过多,导致一些专柜的存货为负数(),还好并发量不是特别大,只存在于小部分专柜而且一般都是-1的状况,没有造...
  • DQ1005
  • DQ1005
  • 2017年09月25日 15:56
  • 450

商品超卖问题

背景 在公司里面我负责的是积分商城一块,里面的积分商品也跟其它商品一样,超卖是绝对不可以的。。。。 刚接手到积分商城 我刚来的时候,积分商城已经有了自家优惠券的功能,整个商城就2件商品:...
  • qq_34581118
  • qq_34581118
  • 2017年07月24日 22:22
  • 273

事务隔离机制原理分析以及是否可以防止订单超卖

事务的隔离机制是指: Read Uncommitted(读取未提交内容) Read Committed(读取提交内容) Repeatable Read(可重读) Serializable(可串行化) ...
  • unix21
  • unix21
  • 2016年10月18日 20:35
  • 1330

mysql处理高并发,防止库存超卖

今天王总又给我们上了一课,其实mysql处理高并发,防止库存超卖的问题,在去年的时候,王总已经提过;但是很可惜,即使当时大家都听懂了,但是在现实开发中,还是没这方面的意识。今天就我的一些理解,整理一下...
  • wangsg2014
  • wangsg2014
  • 2014年03月04日 23:06
  • 3287

mysql处理高并发,防止库存超卖

今天王总又给我们上了一课,其实MySQL处理高并发,防止库存超卖的问题,在去年的时候,王总已经提过;但是很可惜,即使当时大家都听懂了,但是在现实开发中,还是没这方面的意识。今天就我的一些理解,整理一下...
  • u011487470
  • u011487470
  • 2016年08月08日 14:28
  • 1229

深入理解Mysql——锁、事务与并发控制(辟谣)

mysql用的时间也不短了,但从没有做过总结。今天就来总结一下吧mysql服务器逻辑架构每个连接都会在mysql服务端产生一个线程(内部通过线程池管理线程),比如一个select语句进入,mysql首...
  • lemon89
  • lemon89
  • 2016年05月23日 00:21
  • 4912

MySQL锁解决并发问题详解

原文地址:http://leihuang.org/2015/09/10/mysql-lock-concurrency/ 文章分为以下几个要点 问题描述以及解决过程MySQL锁机制数据库加锁...
  • kingice1014
  • kingice1014
  • 2016年08月03日 16:30
  • 2300

MySQL并发控制——事务与事务隔离级别详解

一、首先了解什么是事务 1、事务概念:事务是包含了一组有序的数据库操作命令的序列,它是数据库并发操作的最小控制单位。 2、事务特性:原子性:事务包含的数据库操作命令要么都执行,要么都不执行。 一...
  • zhangliangzi
  • zhangliangzi
  • 2016年06月01日 11:54
  • 1744
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:mysql锁研究系列四(事务在并发情况下避免超卖)
举报原因:
原因补充:

(最多只允许输入30个字)