Mysq详细讲解如何解决库存并发问题

目录
  • 面临的问题
  • 如何实现
  • 需求具体实现的方案
  • 总结

面临的问题

长话短说,假设我们现在面临以下需求

  1. 商品的库存有两千,卖完为止
  2. 某商品本日的售卖只允许卖出一百,卖完为止

如何实现

我提出的方案也很简单,使用乐观锁的方式。

以下是具体的方案

-- stock: 当前库存数 number:扣减的数量 --
 UPDATE t SET stock -= number WHERE stock >= number

外加上事务,便可以实现一个基本的库存扣减操作。大部分情况下,无需担心所谓的“并发问题”。事务具有的特性,会在此处帮你解决的掉这个大难题。

(简单的说:事务会在执行 非查询 的操作的时候,会实现类似锁的功能。直到前面的事物提交或者回滚之前,后续的操作都会被挂住)

需求具体实现的方案

1.商品的库存两千,卖完为止

其实从理论上,想解决这个问题,只依靠上文之中的update语句便可以完成。

具体步骤如下:

  1. 执行UPDATE 语句,查看其结果 。
  2. 若是,则执行后续操作
  3. 若否,代码回滚

具体代码如下

//开始事务
beginTransaction();
// 扣减库存前的业务
// 执行扣减库存操作
boolean reduceStockSuccess = reduceStock();
if(!reduceStockSuccess){
	//扣减库存失败,代码回滚
	rollback();
	return;
}
// 执行扣减库存后的业务操作
//记录库存
writeRecod();
//提交事务
commit();
return;

虽然,程序其实如此便可。但是从个人的角度去看,我还是建议大家多做一点校验,以减少UPDATE程序运行次数。

就比如说,我们可以在前面加一个查询当前库存数量代码。

主要的目的在于,虽然这个校验代码,不能说百分百的解决问题 ,挡住所有的流量。但是却可以挡住大部分无意义的流量,调用UPDATE的次数。

简单来说,就跟我们小时候玩坦克大战一样,虽然我们玩家不能挡住所有的进攻者。但也并不是随随便便谁都可以往我们家基地开炮。

//开始事务
beginTransaction();
// 扣减库存前的业务
int stock = getStock();
if(stock <= 0 ){
	//库存不足,退出程序
	rollback();
	return;
}
// 执行扣减库存操作
boolean reduceStockSuccess = reduceStock();
if(!reduceStockSuccess){
	//扣减库存失败,代码回滚
	rollback();
	return;
}
// 执行扣减库存后的业务操作
//记录库存
writeRecod();
//提交事务
commit();
return;

2 . 日库存数一百 , 卖完为止

该需求相比1来说,问题在于。单从库存表,记录表来说。除非我们在新增到记录表的SQL里面将每日库存数100接入。否则,我们无法通过事务与SQL来帮我们解决并发问题。

但是我们又不可能在记录购买信息的代码内,每日库存数100的逻辑耦合进去。

因此,这个问题对于MYSQL来说是个死局。

若想单靠MYSQL之力若想破局,我们只能依靠将每日库存数的这个逻辑,专门设计一张数据表。

如设计一张商品每日购买数量记录表记录某个商品每日被购买的数量。

在每次购买的时候都更新一下本日购买的数量

 UPDATE day_t SET day_stock += number WHERE day_stock + number <= 100

虽然能解决需求问题,但是表现出来的问题依然是业务耦合进公关表内。

  • 每日购买数量表,不应当仅仅为每日购买上限服务。当前的解决问题的方案,等同于解决问题的同时又制造了一个差不多的问题。只是一个问题转移到了其他部分出问题
  • 即使我们为该需求专门创建一张表,但是随着后续的数据表越来越多,程序的管理性却越来越差,比如后续还会出现周限制,月限制,年限制等等等等。

总结

现在我们可以看出,使用MYSQL的方式虽然简单,但是却有着非常大的局限性。

但这里也并不是说某些方案一定好,却也一定差。

主要看当前的业务,MYSQL的方式,适用于最底层。适合完成某个业务最原始的功能。

到此这篇关于Mysq详细讲解如何解决库存并发问题的文章就介绍到这了,更多相关Mysq库存并发内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Mysql数据库存储过程基本语法讲解

    drop procedure sp_name// 在此之前,小编给大家讲述过MYSQL语法的基本知识,本篇内容,小编通过下面的一个实例,给读者们通过实战中的代码讲解一下基本语法的知识. 一般情况下MYSQL以:结尾表示确认输入并执行语句,但在存储过程中:不是表示结束,因此可以用该命令将:号改为//表示确认输入并执行.存储过程如同一门程序设计语言,同样包含了数据类型.流程控制.输入和输出和它自己的函数库. 一.创建存储过程 1.基本语法: create procedure sp_name() be

  • MySQL数据库存储过程和事务的区别讲解

    事务是保证多个SQL语句的原子型的,也就是要么一起完成,要么一起不完成 存储过程是把一批SQL语句预编译后放在服务器上,然后可以远程调用 存储过程: 一组为了完成特定功能的SQL语句集(或者自定义数据库操作命令集), 根据传入的参数(也可以没有), 通过简单的调用, 完成比单个SQL语句更复杂的功能, 存储在数据库服务器端,只需要编译过一次之后再次使用都不需要再进行编译:主要对存储的过程进行控制. 优点: 1.执行速度快.尤其对于较为复杂的逻辑,减少了网络流量之间的消耗,另外比较重要的一点是存储

  • MySQL数据库存储引擎和分支现状分析

    MySQL随着相应的各主创和内部开发人员的离去,缔造了各个不同的引擎和分支,让MySQL有希望继续发扬光大起来. 在MySQL经历了2008年Sun的收购和2009年Oracle收购Sun的过程中,基本处于停滞发展的情况,在可以预见的未来,MySQL是肯定会被Oracle搁置并且逐步雪藏消灭掉的.MySQL随着相应的各主创和内部开发人员的离去,缔造了各个不同的引擎和分支,让MySQL有希望继续发扬光大起来. 本文大致讲解一下MySQL目前除了主要的 MyISAM.InnoDB.Heap(Memo

  • 更改Mysql数据库存储位置的具体步骤

    一.首先把mysql的服务先停掉. 二.更改MySQL配置文件My.ini中的数据库存储主路径 打开MySQL默认的安装文件夹C:\Program Files\MySQL\MySQL Server 5.1中的my.ini文件,点击记事本顶部的"编辑","查找",在查找内容中输入datadir后并点击"查找下一个"转到"Path to the database root数据库存储主路径"参数设置,找到datadir="

  • Mysq详细讲解如何解决库存并发问题

    目录 面临的问题 如何实现 需求具体实现的方案 总结 面临的问题 长话短说,假设我们现在面临以下需求 商品的库存有两千,卖完为止 某商品本日的售卖只允许卖出一百,卖完为止 如何实现 我提出的方案也很简单,使用乐观锁的方式. 以下是具体的方案 -- stock: 当前库存数 number:扣减的数量 -- UPDATE t SET stock -= number WHERE stock >= number 外加上事务,便可以实现一个基本的库存扣减操作.大部分情况下,无需担心所谓的“并发问题”.事务

  • redis 解决库存并发问题实现数量控制

    目录 一.命令 二.常见场景 三.流程图与代码 redis是单进程,阻塞式,在同一时刻只能处理一个请求,后来的请求需要排队等待. 优点:因为是单进程,所以无需处理并发问题,降低 系统复杂度 缺点:不适合缓存大尺寸对象(超过100kb) 原因: 由于Redis只使用单核,而Memcached可以使用多核,所以平均每一个核上Redis在存储小数据时比Memcached性能更高. 而在100k以上的数据中,Memcached性能要高于Redis,虽然Redis也在存储大数据的性能上进行了优化,但是比起

  • Redis并发访问问题详细讲解

    目录 前言 什么场景需要控制并发访问 并发访问的控制方法 1.加入锁机制 2.操作原子化 小结 前言 我们在使用Redis的过程中,难免会遇到并发访问及数据更新的问题.但很多场景对数据的并发修改是很敏感的,比如库存数据如果没有做好并发读取和更新的版本控制,就会导致严重的业务问题.今天就来说说应该如何做好并发访问及数据更新问题. 什么场景需要控制并发访问 需要控制并发访问,说明这些并发的访问可能会对其他的访问造成影响.比如上面提到的库存问题,若同一时期有多个客户端访问商品A的库存数据,并且可能要更

  • Redis解决库存超卖问题实例讲解

    商品和订单服务间使用MQ 商品服务的库存变化时,通过 MQ 通知订单服务库存变化. 原始的同步流程 查询商品信息 (调用商品服务) 计算总价(生成订单详情) 商品服务扣库存(调用商品服务) 订单入库( 生成订单) // 原始的MySQL同步流程 // 判断此代金券是否加入抢购 SeckillVouchers seckillVouchers = seckillVouchersMapper.selectVoucher(voucherId); AssertUtil.isTrue(seckillVouc

  • Java 详细讲解用堆解决Top-k问题

    目录 1.什么是堆? 堆结构 大根堆 VS 小根堆 大根堆(最大堆) 小根堆(最小堆) 优先级队列(PriorityQueue) 2.top-k问题解决思路 要解决 top-k 问题,我们应该先熟悉一种数据结构 - 堆(优先级队列),已经了解的朋友可以跳过哦. 1.什么是堆? 堆结构 堆其实就是一种二叉树,但是普通的二叉树是以链式结构进行储存数据的,而堆是以数组进行顺序存储数据的.那么什么样的二叉树才适合用顺序存储的方式呢? 我们假设一颗普通的二叉树可以用数组存储,那么就可以得到如下结构: 我们

  • C++超详细讲解贪心策略的设计及解决会场安排问题

    目录 问题描述 贪心策略 算法设计 代码实现 选择结构体 随机输入会议 按结束时间排序 最终会议确定 结束语 问题描述 设有n个会议的集合C={1,2,…,n},其中每个会议都要求使用同一个资源(如会议室),而在同一时间内只能有一个会议使用该资源.每个会议i都有要求使用该资源的起始时间bi和结束时间ei,且bi < ei .如果选择了会议i使用会议室,则它在半开区间[bi, ei)内占用该资源.如果[bi, ei)与[bj , ej)不相交,则称会议i与会议j是相容的.会场安排问题要求在所给的会

  • 基于C#解决库存扣减及订单创建时防止并发死锁的问题

    目录 解决库存扣减及订单创建时防止并发死锁的问题 那么怎样解决死锁? 1. 减少事务的执行时间. 2. 业务锁 测试场景 通过查询库存和订单信息核对库存是否扣减正常 核验结果 解决库存扣减及订单创建时防止并发死锁的问题 在我们日常开发的过程可有会遇到以下错误 事务(进程 ID 82)与另一个进程被死锁在 锁 资源上,并且已被选作死锁牺牲品.请重新运行该事务 很多开发人员对于这个问题的排查起来是比较困难的,而生产生的原因多种多样,很多人认是因为表中的数据太多了同时操作的人多人才会产生这种错误,下面

  • Python多进程并发与同步机制超详细讲解

    目录 多进程 僵尸进程 Process类 函数方式 继承方式 同步机制 状态管理Managers 在<多线程与同步>中介绍了多线程及存在的问题,而通过使用多进程而非线程可有效地绕过全局解释器锁. 因此,通过multiprocessing模块可充分地利用多核CPU的资源. 多进程 多进程是通过multiprocessing包来实现的,multiprocessing.Process对象(和多线程的threading.Thread类似)用来创建一个进程对象: 在类UNIX平台上,需要对每个Proce

  • GoLang并发机制探究goroutine原理详细讲解

    目录 1. 进程与线程 2. goroutine原理 3. 并发与并行 3.1 在1个逻辑处理器上运行Go程序 3.2 goroutine的停止与重新调度 3.3 在多个逻辑处理器上运行Go程序 通常程序会被编写为一个顺序执行并完成一个独立任务的代码.如果没有特别的需求,最好总是这样写代码,因为这种类型的程序通常很容易写,也很容易维护.不过也有一些情况下,并行执行多个任务会有更大的好处.一个例子是,Web 服务需要在各自独立的套接字(socket)上同时接收多个数据请求.每个套接字请求都是独立的

  • 超详细讲解Linux C++多线程同步的方式

    目录 一.互斥锁 1.互斥锁的初始化 2.互斥锁的相关属性及分类 3,测试加锁函数 二.条件变量 1.条件变量的相关函数 1)初始化的销毁读写锁 2)以写的方式获取锁,以读的方式获取锁,释放读写锁 四.信号量 1)信号量初始化 2)信号量值的加减 3)对信号量进行清理 背景问题:在特定的应用场景下,多线程不进行同步会造成什么问题? 通过多线程模拟多窗口售票为例: #include <iostream> #include<pthread.h> #include<stdio.h&

随机推荐