mysql - 面试的时候遇到的问题,关于PHP并发

php中文网
发布: 2016-06-06 20:32:17
原创
1259人浏览过

大概就是 mysql的一张表存放着某个用户的余额,下面我写伪代码了。

$sql=select * from user wherer 余额 > 10 and id=1;
//如果有余额进行逻辑处理最后在减去扣款。
if($sql){
echo '请求它接口';
$sql=update user set 余额=余额-10;//关键就在这里了,如果减完了就相当于没余额了,但是由于并发,第二个人查询的时候是有的,他也进了这个条件。怎么避免这种情况

}else{

echo '余额不足';
}

回复内容:

大概就是 mysql的一张表存放着某个用户的余额,下面我写伪代码了。

$sql=select * from user wherer 余额 > 10 and id=1;
//如果有余额进行逻辑处理最后在减去扣款。
if($sql){
echo '请求它接口';
$sql=update user set 余额=余额-10;//关键就在这里了,如果减完了就相当于没余额了,但是由于并发,第二个人查询的时候是有的,他也进了这个条件。怎么避免这种情况

}else{

echo '余额不足';
}

2种解决办法:”for update“的悲观锁,或者使用”版本号“的乐观锁,http://segmentfault.com/q/1010000002905539

立即学习PHP免费学习笔记(深入)”;

MyBB 国外最好的免费论坛
MyBB 国外最好的免费论坛

MyBB的全称是mybboard,是一个基于PHP+MySQL搭建,功能强大,高效的开源论坛系统。 MyBB 使用了标准的论坛结构和模式,所以您的用户可以在您的论坛获得良好的用户体验。用户可以通过用户控制面板来自定义他们访问论坛的方式或者自定义他们想看到的论坛的内容,他们还可以方便地发表和答复一个主题并且标记与他们有关的主题。论坛管理员和版主可以使用MyBB的内置编辑器和版主工具等功能,控制并维

MyBB 国外最好的免费论坛 95
查看详情 MyBB 国外最好的免费论坛

$sql = select ... for update, 先给锁了试试

楼上说的"版本号"乐观锁不错,不需要数据库事务支持:
就像防止多人编辑一样,给表弄一个版本号字段.
获取数据时拿到版本号和余额,写入时比对版本号,相同则插入,并把版本号加1.

<code>SELECT balance,version AS last_version FROM user WHERE id=1 AND balance>10;
UPDATE user SET balance=balance-10,version=version+1 WHERE id=1 AND version=last_version;
</code>
登录后复制

唉,题主你被坑了,这哪里是PHP问题,这明显是数据库问题。

正确的做法是,用存储过程 + 事务 + 锁。
而且一点都不简单,使用存储过程,你需要依次判断:
---->账号是否存在
---->余额够不够
---->数据修改后还要验证是否成功、是否修改正确(某些数据库有bug会导致没修改,或改错。因此自己要先用sql计算一次修改结果用于验证)

反对几种答案:
1.使用乐观锁。这要对表进行改动,增加last_version字段,明显不科学。
2.记录余额、或者在update时先where amount > 10,这也不科学,如果之前该用户的账号被删除了呢?
3.使用队列。以后系统的瓶颈集中在这里,看看老板会不会打死你。

大并发可队列操作库。

最简单的方式是在sql里加判断
update user set amount=amount-10 where amount > 10
如果执行影响列数为0的话,就提示报错

有2种办法
方法1:
先查询一次余额,记为初始余额.
然后
$sql=update user set 余额=余额-10 where 初始余额>0
然后判断这条sql执行影响的行数,就可以避免并发导致余额为负的情况.
方法2:
$sql = update user set 余额=case when 余额>10 then 余额-10 else 余额 end where...
然后看影响行数.

相关标签:
PHP速学教程(入门到精通)
PHP速学教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号