Thinkphp5 实现悲观锁
悲观锁介绍(百科):
悲观锁,正如其名,它指的是对数据被外界(包括本系统当前的其他事务,以及来自外部系统的事务处理)修改持保守态度,因此,在整个数据处理过程中,将数据处于锁定状态。悲观锁的实现,往往依靠数据库提供的锁机制(也只有数据库层提供的锁机制才能真正保证数据访问的排他性,否则,即使在本系统中实现了加锁机制,也无法保证外部系统不会修改数据)。
使用场景举例:以MySQL InnoDB为例
商品goods表,假设商品的id为2,购买数量为1,status为1表示上架中,2表示下架。现在用户购买此商品,在不是高并发的情况下处理逻辑是:
- 查找此商品的信息;
 - 检查商品库存是否大于购买数量;
 - 修改商品库存和销量;
 
上面这种场景在高并发访问的情况下很可能会出现问题。如果商品库存是100个,高并发的情况下可能会有1000个同时访问,在到达第2步的时候,都会检测通过。这样会出现商品库存是-900个的情况。显然着不满足需求!!!
使用悲观锁在处理。
当我们在查询出goods信息后就把当前的数据锁定,直到我们修改完毕后再解锁。那么在这个过程中,因为goods被锁定了,就不会出现有第三者来对其进行修改了。
注:要使用悲观锁,我们必须关闭mysql数据库的自动提交属性,因为MySQL默认使用autocommit模式,也就是说,当你执行一个更新操作后,MySQL会立刻将结果进行提交。
/**
* thinkphp使用悲观锁。悲观锁需要配合事务一起使用
* 商品表。购买数量为1,先锁定该商品,不让其他操作减库存。
*/
public function mysql_lock(){
$num = 1;
$goods_id = 2;
$model = \db('goods');
$model->execute('set autocommit=0');
$model->startTrans();
//使用主键或者其他索引字段时为行级锁,否则为表级锁
$where['id'] = $goods_id;
$where['status'] = 1;
$goods_info = $model->lock(true)->where($where)->find();
if(empty($goods_info)){
return '商品不存在';
}
$total = $goods_info['total']; //商品库存
$sell = $goods_info['sell']; //商品销量
if($total<$num){
return '库存不足';
}
$data['total'] = $total-$num;
$data['sell'] = $sell+$num;
$res = $model->where(array('id'=>$goods_id))->update($data);
if($res){
$order_model = \db('orders');
$order_data['uid'] = rand(1000,9999);
$order_data['status'] = 1;
$order_data['create_time'] = date('Y-m-d H:i:s');
$order_res = $order_model->insert($order_data);
if($order_res){
$model->commit();
}else{
$model->rollback();
}
}else{
$model->rollback();
}
exit; } /**
* 不加锁的情况
* @return string
*/
public function mysql_unlock(){
$num = 1;
$goods_id = 2;
$model = \db('goods');
$model->execute('set autocommit=0');
$model->startTrans();
$where['id'] = $goods_id;
$where['status'] = 1;
$goods_info = $model->where($where)->find();
if(empty($goods_info)){
return '商品不存在';
}
$total = $goods_info['total']; //商品库存
$sell = $goods_info['sell']; //商品销量
if($total<$num){
return '库存不足';
}
$data['total'] = $total-$num;
$data['sell'] = $sell+$num;
$res = $model->where(array('id'=>$goods_id))->update($data);
if($res){
$order_model = \db('orders');
$order_data['uid'] = rand(1000,9999);
$order_data['status'] = 1;
$order_data['create_time'] = date('Y-m-d H:i:s');
$order_res = $order_model->insert($order_data);
if($order_res){
$model->commit();
}else{
$model->rollback();
}
}else{
$model->rollback();
}
exit; }
加锁和不加锁的测试请看下篇文章【Thinkphp5 用ab压力测试工具测试高并发请求】。
Thinkphp5 实现悲观锁的更多相关文章
- mysql悲观锁总结和实践--转
		
原文地址:http://chenzhou123520.iteye.com/blog/1860954 最近学习了一下数据库的悲观锁和乐观锁,根据自己的理解和网上参考资料总结如下: 悲观锁介绍(百科): ...
 - 【mysql】关于悲观锁
		
关于mysql中的锁 在并发环境下,有可能会出现脏读(Dirty Read).不可重复读(Unrepeatable Read). 幻读(Phantom Read).更新丢失(Lost update)等 ...
 - 【MySQL】悲观锁&乐观锁
		
悲观锁与乐观锁是两种常见的资源并发锁设计思路,也是并发编程中一个非常基础的概念.本文将对这两种常见的锁机制在数据库数据上的实现进行比较系统的介绍. 悲观锁(Pessimistic Lock) 悲观锁的 ...
 - mysql-mysql悲观锁和乐观锁
		
1.mysql的四种事务隔离级别 I. 对于同时运行多个事务,当这些事务访问数据库中的相同数据时,如果没有采取必要的隔离机制,就会导致各种并发问题. (1)脏读: 对于两个事物 T1, T2, T1 ...
 - 【Oracle】悲观锁和乐观锁
		
悲观锁 如select * for update 悲观锁大多数情况下依靠数据库的锁机制实现,以保证操作最大程度的独占性.但随之而来的就是数据库性能的大量开销,特别是对长事务而言,这样 ...
 - SQL-乐观锁,悲观锁之于并发
		
每次写博客,第一句话都是这样的:程序员很苦逼,除了会写程序,还得会写博客!当然,希望将来的一天,某位老板看到此博客,给你的程序员职工加点薪资吧!因为程序员的世界除了苦逼就是沉默.我眼中的程序员大多都不 ...
 - mysql悲观锁总结和实践
		
使用场景举例:以MySQL InnoDB为例商品t_goods表中有一个字段status,status为1代表商品未被下单,status为2代表商品已经被下单,那么我们对某个商品下单时必须确保该商品s ...
 - Oracle的悲观锁和乐观锁---摘抄
		
1.无论是选择悲观锁策略,还是乐观锁策略.如果一个对象被上了锁,那么该对象都会受这个锁的控制和影响.如果这个锁是个排它锁,那么其它会话都不能修改它. 2.选择悲观锁策略,还是乐观锁策略,这主要是由应用 ...
 - 快钱支付与Sql Server的乐观锁和悲观锁
		
在实际的多用户并发访问的生产环境里边,我们经常要尽可能的保持数据的一致性.而其中最典型的例子就是我们从表里边读取数据,检查验证后对数据进行修改,然后写回到数据库中.在读取和写入的过程中,如果在多用户并 ...
 
随机推荐
- ReactiveCocoa源码解析(四) Signal中的静态属性静态方法以及面向协议扩展
			
上篇博客我们聊了Signal的几种状态.Signal与Observer的关联方式以及Signal是如何向关联的Observer发送事件的.本篇博客继续上篇博客的内容,来聊一下Signal类中静态的ne ...
 - eclipse 常用快捷键 及 windows快捷键
			
Eclipse常用快捷键 打开Eclipse快捷键的快捷键 Ctrl+Shift+L 快捷键 描述 原英文描述 Ctrl+Shift+P 定位到光标所在处的括号的另一半括号的位置 Go to Matc ...
 - Mycat在MySQL主从模式(1主1从)下读写分离和及自动切换模式的验证
			
实验环境 两台Centos7 MySQL5.7.12 IP地址为:192.168.10.36 192.168.10.37 一台Centos7 Mycat IP地址为:192.168.10.31 一 ...
 - 使用css3实现小菊花加载效果
			
使用css3实现小菊花加载效果 最常见的就是我们用到的加载动画.加载动画的效果处理的好,会给页面带来画龙点睛的作用,而使用户愿意去等待.而页面中最常用的做法是把动画做成gif格式,当做背景图或是img ...
 - 列表的系列操作(python)
			
除了定义和切片外,这里总结下系列的操作: # hanbb come on! names = ["hbb",'tian','bao','cheng'] #Add names.appe ...
 - Android - 读取JSON文件数据
			
Android读取JSON文件数据 JSON - JavaScript Object Notation 是一种存储和交换文本信息的语法. JSON对象在花括号中书写.用逗号来分隔值. JSON数组在方 ...
 - 20170711_map/reduce
			
js: map: var arr = [1,2,3,4,5]; var res = arr.map(function(x){ return x * x; }); //res 现在 = [1,4,9,1 ...
 - python的数据类型及操作
			
简述python的几种简单的数据类型及使用方式 字符串 字符串是不可变数据类型,拥有多种内置方法可以操作. 创建字符串就是给变量分配一个字符串的值即可.通常用引号创建字符串. tell = 'my n ...
 - 工程经验总结之吹水"管理大境界"
			
1.个人认为项目管理最核心的能力是预见风险和快速解决风险的能力. 从实践来看,没有百分百的完美计划,任何计划都有出现偏差的可能,或者说计划总是不会按照最初的设定去完美执行的. 项目经理存在的主要价值就 ...
 - jquery html5 file 上传图片显示图片
			
jquery js 的代码:不同浏览器下的路径 //建立一個可存取到該file的url function getObjectURL(file) { var url = null ; i ...