应用场景:PHP模拟购买,商品数量大于0才能购买
常见代码:
<?php //连接数据库 $con=mysqli_connect("localhost","ihuohuo","927464cy","ihuohuo"); //查询商品数量是否大于0 $res=mysqli_fetch_assoc(mysqli_query($con,'SELECT total FROM shop WHERE id=1 LIMIT 1')); if($res['total']>0){ mysqli_query($con,'UPDATE shop SET total=total-1 WHERE id=1'); } unset($res); mysqli_close($con); ?>
以上代码在少量访问情况下不会出现问题,并发量较高会导致商品数量为负值
修正后代码:
<?php $con=mysqli_connect("localhost","ihuohuo","927464cy","ihuohuo"); mysqli_query($con, 'BEGIN'); $res=mysqli_fetch_assoc(mysqli_query($con,'SELECT total FROM shop WHERE id=1 LIMIT 1 FOR UPDATE')); if($res['total']>0){ mysqli_query($con,'UPDATE shop SET total=total-1 WHERE id=1 '); } mysqli_query($con, 'COMMIT'); unset($res); mysqli_close($con); ?>
解析:在mysql中通过 FOR UPDATE锁住本行记录,只有事务commit之后其他进程才能继续操作本条记录,一定要注意3点, FOR UPDATE锁表必须在事务begin和commit之间完成。
当然您可以通过文件锁完成,mysql行锁的开销还是比较大的,本站搜索文件锁。
通过http推送消息给socket,socket服务再向客户端推送<?php /* * Socket推送 * 请用守护进程方式启动php msgservice.php & (socket只...
if($_SERVER['REQUEST_METHOD'] == 'POST') { echo('This is post '); } elseif ($_SERVER['...
Redis提供了发布订阅功能,可以用于消息的传输,Redis的发布订阅机制包括三个部分,发布者(publisher),订阅者(subscriber)和频道(channel)。 发布者和订阅者都是Redis客户端,Channel则为Redis服务器端,发布者将消息发送到某个的频道,订阅了这个...
<?php /** * @throws Exception */ function curl() { throw new \Exception('err...
<?php //php7+ define('CONFIG', [ 'MYSQL' => '127.0.0.1',  ...
<?php //如果支持exec函数,可以使用的方式 exec('chcp 65001'); //如果exec函数因安全问题禁用,可以使用的方式 pclose(popen('chcp 65001', 'r'));...