mysql扣减库存_扣库存之mysql方案讨论
一、想要实现什么功能?
点击商品购买按钮;
扣库存;
扣除用户的余额;
给用户背包增加商品;
二、可能会有高并发出现的场景?
同一个用户,开启两个客户端,同时购买同一个商品;
同一个用户,开启两个客户端,同时购买不同的商品;
两个不同的用户,同时购买同一个商品;
两个不同的用户,同时购买不同的商品;
同一个用户,开启两个客户端,同时购买多个商品,一个客户端购买商品a、b,另一个客户端购买商品b、a
不同的用户,同时购买多个商品,一个购买商品a、b,另一个购买商品b、a
三、不同场景逻辑梳理与解决方案
1. 场景一:同一个用户,开启不同的客户端,购买同一个商品
(1)上图的问题,如何解决?
(2)要明白商品的库存和用户的是两个线程同时操作;相当于两个线程同时修改同一份资源,这时候想到锁机制。
(3)将操作的同一个资源锁上,只有锁释放掉才能被另一个线程进行修改;
(4)select stock from table where id=1 for update;//将操作的那条记录加排他锁
(5)update table set stock=remainStock where id=1;//这时候这条记录已经锁上了,可以更新库存
(6)最后事务结束才能释放掉锁,在当前事务还没有commit的时候,另一个线程一直在等待锁过程中,直到锁释放获取到锁。
2.场景二:同一个用户,开启两个客户端,同时购买不同的商品
(1)购买不同的商品,扣库存不存在两个线程操作同一个资源的问题。
(2)但是同一个用户,扣余额的时候,还会出现两个线程操作同一个资源的问题,所以完全可以复用场景一的解决方法,直接给那个资源加一把排他锁
3.场景三:两个不同的用户,同时购买同一个商品
(1)这种问题实际上还是不同线程操作同一个资源的问题,加锁解决
4.场景四:两个不同的用户,同时购买不同的商品;
(1)这种场景最安全,不会出现操作同一个资源的问题
5.场景五:同一个用户,开启两个客户端,同时购买多个商品,一个客户端购买商品a、b,另一个客户端购买商品b、a
(1)一个线程循环对商品a、b进行减库存,另一个线程玄幻对商品b、a进行减库存;
(2)这时当线程一对a记录加了排他锁,另一个线程二对b记录加了排他锁;
(3)当两线程都进入第二层循环的时候,线程一要对b减库存,线程二要对a减库存;
(4)当前线程一拿着a记录的锁,等待b记录释放锁,线程二拿着b记录的锁,等待a记录释放锁,两个线程互相等待对方释放锁,造成死锁;
(5)所以可以得到结论,按照以前的加排他锁查询再更新库存的方式有可能造成死锁
(6)想要解决,那么可以给要加锁的记录都按照同一个顺序加锁
(7)select * from table where id in (a,b) order by id asc;//先对商品记录排序然后再加锁减库存
6.场景六:不同的用户,同时购买多个商品,一个购买商品a、b,另一个购买商品b、a
(1)这个其实和场景五是一个问题,排序加锁解决死锁问题
三、思考与优化
1.以上其实就是讨论了两个核心的问题:
(1)一个是多个线程同时操作同一个资源的处理方式(加锁)
(2)另一个问题就是加锁过程中导致的死锁解决方式(对加锁顺序进行排序)
2.上边我们讨论的减库存方式,都是先进行查询,再进行更新,那有没有一种方式让两个语句合在一起?
(1)update table set stock = stock - num where id = xxx and stock >= num;//在update语句里边直接查询更新,同时保证库存不会被减为0,防止了超卖的问题
四、总结
1.并发问题,实际上就是解决多个进程同时操作同一个资源的问题——加锁
2.加锁过程中,也要注意别弄成死锁——-给加锁顺序进行排序
3.注意,这些讨论都是基于在一个事务中实现的
4.innodb的默认隔离级别是第三级,可重复读,两个事务的修改互相是不可见的,对于不同进程操作同一个资源的时候,更要注意加锁的问题
作者:繁星落眼眶
mysql扣减库存_扣库存之mysql方案讨论相关推荐
- 电商扣减库存_严选库存中心性能优化
性能是技术同学时常关注的问题,但在不同的业务模式下.业务板块中开展的优化手段又不尽相同.本文主要介绍基于严选现有业务模式,在未显著降低数据一致性的情况下如何进行库存的性能优化以满足大促活动的要求. 背 ...
- mysql去掉秒杀场景_秒杀场景下mysql减库存逻辑优化
[问题背景] 某天早上做活动,流量大量增长,导致大量更新库存操作失败. 操作mysql返回的错误均为"Lost Connection to mysql server",即mysql ...
- python目前有多少库存_统计库存数量的软件,库存有多少,一键统计查询
管理好公司的仓库,就要做到商品库存数量清晰明了,而且还可以对公司仓库的实时动态变化进行管理.使用传统的手工记账的方式,虽然可对商品库存情况进行统计,但是,这个数据做不到数据实时更新,尤其是难以做到多个 ...
- mysql connection是什么_记一次MySQL出现too many connection
今天中午的时候突然接到报警,MySQL连接数暴增..本来设置的max_conntion=6000, 这个数值连接已经够用.接到报警速度连接服务器连接mysql总是报如下错误: [mysql@local ...
- golang mysql连接池原理_[Go] golang实现mysql连接池
golang中连接mysql数据库,需要使用一个第三方类库github.com/go-sql-driver/mysql,在这个类库中就实现了mysql的连接池,并且只需要设置两个参数就可以实现 一般连 ...
- mysql 数据库字符集转换_字符集介绍及mysql数据库编码转换
一.字符集介绍: 1.ASCII ASCII是英文American Standard Code for Information Interchange的缩写,美国标准信息交换代码是由美国国家标准学会( ...
- mysql 查询编码转换_字符集介绍及mysql数据库编码转换
一.字符集介绍: 1.ASCII ASCII是英文American Standard Code for Information Interchange的缩写,美国标准信息交换代码是由美国国家标准学会( ...
- mysql崩溃恢复过程_一起看下MySQL的崩溃恢复到底是怎么回事
思考一个问题 为什么在你当update时,事物提交之前先不断的写redo log呢? 如果你看过白日梦前面介绍buffer pool的文章,这个问题的答案想必你也能很快的想出来:MySQL为了提高性能 ...
- mysql事件探查器_【干货】Mysql的事件探查器-之Mysql-Proxy代理实战一(安装部署与实战sql拦截与性能监控)...
1:资料参考 https://blog.csdn.net/coldljy/article/details/3168906 https://www.cnblogs.com/jwentest/p/8552 ...
- python django mysql写入中文乱码_解决django 向mysql中写入中文字符出错的问题
之前使用django+mysql建立的一个站点,发现向数据库中写入中文字符时总会报错,尝试了修改settings文件和更改数据表的字符集后仍不起作用.最后发现,在更改mysql的字符集后,需要重建数据 ...
最新文章
- BeagleBone Black快速入门教程第1章嵌入式Linux之于Maker们
- AdaBoost算法源码分析
- Server 2008 R2 AD RMS完整部署:一、用户创建篇
- Spring Boot源码:SpringBootExceptionReporter
- info命令Linux,Linux zipinfo命令
- linux比windows更快吗,linux比windows快很多倍除了算法的优势 有没C比C++快的原因?
- MS SQL Server和Oracle对数据库事务处理的差异性
- python创建矩阵_python中Numpy的属性与创建矩阵
- Jmeter中java接口测试
- 推荐系统实践:基于数据集MovieLens构造简单推荐系统
- json在线解析工具
- 为什么显示D盘可用空间不多,但是明明包括隐藏文件也没有用那么多内存?(内含解决方案)
- 《数据结构》-图的邻接表表示法(四)
- JSON解析错误:无法构建内部类的实例
- 关于康托展开的用途及写法
- 大疆工程师:如何利用6年时间成为一名优秀的机器人工程师
- 蚂蚁金服对收购英支付企业不予置评,雷军忆当年“被迫”当金山CEO往事 | 雷锋早报...
- 【逻辑】500桶酒,其中1桶是毒酒,找毒酒
- java语言在scada系统中的应用_基于J2EE平台的SCADA系统实现
- html5在手机端调用摄像头的介绍以及新特性