解决类似超卖问题,mysql加锁
来源:互联网 发布:seo 外链 编辑:程序博客网 时间:2024/06/06 16:52
情景:(代码环境Thinkphp)
我有一个流量充值接口,里面的操作大概是这样:
1.生产一个订单
2.查询用户余额是否足够,足够继续,不足提示错误
3.扣除用户余额,并生产账户记录
4.将订单设为已充值
$model->startTrans(); // 启动事务
try {
$uInfo = D('User')->where(array('id'=>$uInfo['id']))->find();
// 判断用户余额是否足够
if ($uInfo['balance'] <= 0 || $uInfo['balance'] < $orderData['total_price'] ) {
throw new \Think\Exception("用户余额不足",5202);
}
// 扣除用户余额,并生产账户记录
if ( !D('AccountRecord')->consume($orderData['total_price'],$orderData['user_id'],'充值流量,扣除余额') ) {
throw new \Think\Exception("扣除用户余额失败",5302);
}
// 将订单设为成功
if ( !$model->where(array('id'=>$order_id))->save(array('order_status'=>1)) ) {
throw new \Think\Exception("订单设置成功失败",5303);
}
$model->commit(); //事务提交
echo return_result(array('code'=>'2000','msg'=>'充值成功'));exit();
} catch (\Think\Exception $e) {
$model->rollback(); //事务回滚
echo return_result(array('code'=>$e->getCode(),'msg'=>$e->getMessage()));exit();
}
这样看似没什么问题,一般情况下确实也没什么事,但是高并发情况下,就有问题,具体问题如下:
假如有个用户A同时调用了2次接口,A的账户余额为10,而一次的请求会扣除10的金额,那么,A的2次接口是同时进行的,2次一开始获取的用户余额都是10,这就是问题了
第一次请求,会将A的余额变为0,按理说,第二次请求会因为余额不足而不成功,但是,由于2次请求是并发一起进来的,那么第二次获取的余额上也是10,所以会继续扣款,
此时用户余额为-10
解决方法如下:
将$uInfo = D('User')->where(array('id'=>$uInfo['id']))->find();
变成:$uInfo = D('User')->lock(true)->where(array('id'=>$uInfo['id']))->find();
进行加锁后,成功将问题解决,but,有相对的代价,即性能增加了负担:
这是加锁前的:
这是加锁后的:
0 0
- 解决类似超卖问题,mysql加锁
- AutoLock 解决加锁后忘记解锁问题
- 解决mysql超8小时连接的问题
- 如何正解决库存超卖问题
- mysql的加锁与死锁问题
- 解决两个窗体类似问题
- java 线程六-解决线程安全隐患问题-加锁
- 一个mysql解决的问题:游标、字符串操作 类似另一篇 sql
- 如何解决秒杀的性能问题和超卖
- 解决超卖思路
- 电商系列---mysql高并发超库存卖问题
- MySQL 加锁策略
- mysql加锁机制
- MySQL 加锁处理分析
- MySQL 加锁处理分析
- MySQL 加锁处理分析
- MySQL 加锁处理分析
- MySQL 加锁处理分析
- view里面的tableview顶部被view的导航栏盖住了的问题
- 接口篇(5.2)-03. 接口的合并 ❀ 飞塔 (Fortinet) 防火墙
- 给ListView的Item添加CheckBox,长按调出CheckBox,然后通过点击进行选中和取消
- 【codevs 1007】级数求和
- 唯品会基于Kubernetes(k8s)网络方案演进
- 解决类似超卖问题,mysql加锁
- bzoj1637: [Usaco2007 Mar]Balanced Lineup ——by lethalboy
- javascript 关闭浏览器怎么清空所有的cookie
- 获取不重复的随机数(抽签原理)
- Spring Batch 之 Sample(Hello World)(三)
- Linux系统文件防篡改脚本第一版
- 使用WARN_ON来追溯函数的调用关系
- concurrent包与线程池
- 栅格数据说明