悲观锁介绍(百科):

悲观锁,正如其名,它指的是对数据被外界(包括本系统当前的其他事务,以及来自外部系统的事务处理)修改持保守态度,因此,在整个数据处理过程中,将数据处于锁定状态。悲观锁的实现,往往依靠数据库提供的锁机制(也只有数据库层提供的锁机制才能真正保证数据访问的排他性,否则,即使在本系统中实现了加锁机制,也无法保证外部系统不会修改数据)。


使用场景举例:以MySQL InnoDB为例

商品goods表,假设商品的id为2,购买数量为1,status为1表示上架中,2表示下架。现在用户购买此商品,在不是高并发的情况下处理逻辑是:

  1. 查找此商品的信息;
  2. 检查商品库存是否大于购买数量;
  3. 修改商品库存和销量;

上面这种场景在高并发访问的情况下很可能会出现问题。如果商品库存是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 实现悲观锁的更多相关文章

  1. mysql悲观锁总结和实践--转

    原文地址:http://chenzhou123520.iteye.com/blog/1860954 最近学习了一下数据库的悲观锁和乐观锁,根据自己的理解和网上参考资料总结如下: 悲观锁介绍(百科): ...

  2. 【mysql】关于悲观锁

    关于mysql中的锁 在并发环境下,有可能会出现脏读(Dirty Read).不可重复读(Unrepeatable Read). 幻读(Phantom Read).更新丢失(Lost update)等 ...

  3. 【MySQL】悲观锁&乐观锁

    悲观锁与乐观锁是两种常见的资源并发锁设计思路,也是并发编程中一个非常基础的概念.本文将对这两种常见的锁机制在数据库数据上的实现进行比较系统的介绍. 悲观锁(Pessimistic Lock) 悲观锁的 ...

  4. mysql-mysql悲观锁和乐观锁

    1.mysql的四种事务隔离级别 I. 对于同时运行多个事务,当这些事务访问数据库中的相同数据时,如果没有采取必要的隔离机制,就会导致各种并发问题. (1)脏读: 对于两个事物 T1, T2, T1 ...

  5. 【Oracle】悲观锁和乐观锁

    悲观锁     如select * for update     悲观锁大多数情况下依靠数据库的锁机制实现,以保证操作最大程度的独占性.但随之而来的就是数据库性能的大量开销,特别是对长事务而言,这样  ...

  6. SQL-乐观锁,悲观锁之于并发

    每次写博客,第一句话都是这样的:程序员很苦逼,除了会写程序,还得会写博客!当然,希望将来的一天,某位老板看到此博客,给你的程序员职工加点薪资吧!因为程序员的世界除了苦逼就是沉默.我眼中的程序员大多都不 ...

  7. mysql悲观锁总结和实践

    使用场景举例:以MySQL InnoDB为例商品t_goods表中有一个字段status,status为1代表商品未被下单,status为2代表商品已经被下单,那么我们对某个商品下单时必须确保该商品s ...

  8. Oracle的悲观锁和乐观锁---摘抄

    1.无论是选择悲观锁策略,还是乐观锁策略.如果一个对象被上了锁,那么该对象都会受这个锁的控制和影响.如果这个锁是个排它锁,那么其它会话都不能修改它. 2.选择悲观锁策略,还是乐观锁策略,这主要是由应用 ...

  9. 快钱支付与Sql Server的乐观锁和悲观锁

    在实际的多用户并发访问的生产环境里边,我们经常要尽可能的保持数据的一致性.而其中最典型的例子就是我们从表里边读取数据,检查验证后对数据进行修改,然后写回到数据库中.在读取和写入的过程中,如果在多用户并 ...

随机推荐

  1. 【Android Developers Training】 23. 序言:保存数据

    注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...

  2. accp8.0转换教材第3章MySQL高级查询(一)理解与练习

    一.单词部分 ①constraint约束②foreign外键③references参考 ④subquery子查询⑤inner内部的⑥join连接 二.预习部分 1.修改表SQL语句的关键字是什么 RE ...

  3. Vijos 1033 整数分解(版本2)

    描述 整数分解(版本2) 一个正整数可以分解成若干个自然数之和.请你编一个程序,对于给出的一个正整数n(1<=n<=1500),求出满足要求的分解方案,并使这些自然数的乘积m达到最大. 例 ...

  4. Elasticsearch学习随笔(一)--原理理解与5.0核心插件部署过程

    最近由于要涉及一些安全运维的工作,最近在研究Elasticsearch,为ELK做相关的准备.于是把自己学习的一些随笔分享给大家,进行学习,在部署常用插件的时候由于是5.0版本的Elasticsear ...

  5. ARP欺骗分析

    (作者原创,欲转载请说明出处)1.arp介绍    arp:地址解析协议;将IP地址映射为MAC地址.2.为什么要有arp    平时上网我们都知道要有一个IP地址才能上网,那arp用来干嘛的呢?如果 ...

  6. 容器_JDK源码分析_自己简单实现ArrayList容器

    这几天仔细研究下关于ArrayList容器的jdk源码,感觉收获颇多,以前自己只知道用它,但它里面具体是怎样实现的就完全不清楚了.于是自己尝试模拟写下java的ArrayList容器,简单了实现的Ar ...

  7. DotNetCore跨平台~文章索引~永久更新

    本索引目录主要包括仓储大叔对dotnet core架构的研究与知识积累,从2016年开始进行撰写,到今天已经有一年多了,其中有一些小知识,小技巧,小应用,希望给大家在开发时一些启发,也希望dotnet ...

  8. java基础02 数据类型转

    一.回答问题 float f1 = 6.66f; float f2 = (float) 6.67; f1==f2? /** * * @author sun * */ public class Demo ...

  9. 浅谈Notepad++选中行操作+快捷键+使用技巧【超详解】

    Notepad++选中行操作 快捷键 使用技巧 用Notepad++写代码,要是有一些重复的代码想copy一下,还真不容易,又得动用鼠标,巨烦人.... 有木有简单的方法呢,确实还是有的不过也不算太好 ...

  10. Python运维开发基础-概述-简介

    Python基础知识分为以下几块 1.Python概述 2.基础语法 3.数据结构 4.Python进阶 5.实训案例 一.Python概述 1.Python简介 2.Hello World 3.搭建 ...