数据库管理系统(DBMS)中的并发控制的任务是确保在多个事务同时存取数据库中同一数据时不破坏事务的隔离性和统一性以及数据库的统一性。

乐观并发控制(乐观锁)和悲观并发控制(悲观锁)是并发控制主要采用的技术手段。

无论是悲观锁还是乐观锁,都是人们定义出来的概念,可以认为是一种思想。其实不仅仅是数据库系统中有乐观锁和悲观锁的概念,像memcache、hibernate、tair等都有类似的概念。

针对于不同的业务场景,应该选用不同的并发控制方式。所以,不要把乐观并发控制和悲观并发控制狭义的理解为DBMS中的概念,更不要把他们和数据中提供的锁机制(行锁、表锁、排他锁、共享锁)混为一谈。其实,在DBMS中,悲观锁正是利用数据库本身提供的锁机制来实现的。

下面来分别学习一下悲观锁和乐观锁。

悲观锁:

在关系数据库管理系统里,悲观并发控制(又名“悲观锁”,Pessimistic Concurrency Control,缩写“PCC”)是一种并发控制的方法。它可以阻止一个事务以影响其他用户的方式来修改数据。如果一个事务执行的操作都某行数据应用了锁,那只有当这个事务把锁释放,其他事务才能够执行与该锁冲突的操作。悲观并发控制主要用于数据争用激烈的环境,以及发生并发冲突时使用锁保护数据的成本要低于回滚事务的成本的环境中。

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

在数据库中,悲观锁的流程如下:

在对任意记录进行修改前,先尝试为该记录加上排他锁(exclusive locking)。

如果加锁失败,说明该记录正在被修改,那么当前查询可能要等待或者抛出异常。 具体响应方式由开发者根据实际需要决定。

如果成功加锁,那么就可以对记录做修改,事务完成后就会解锁了。

要使用悲观锁,我们必须关闭mysql数据库的自动提交属性,因为MySQL默认使用autocommit模式,也就是说,当你执行一个更新操作后,MySQL会立刻将结果进行提交。 set autocommit=0;

//0.开始事务

begin;/begin work;/start transaction; (三者选一就可以)

//1.查询出商品信息

select status from t_goods where id=1 for update;

//2.根据商品信息生成订单

insert into t_orders (id,goods_id) values (null,1);

//3.修改商品status为2

update t_goods set status=2;

//4.提交事务

commit;/commit work;

上面的查询语句中,我们使用了 select…for update 的方式,这样就通过开启排他锁的方式实现了悲观锁。此时在t_goods表中,id为1的 那条数据就被我们锁定了,其它的事务必须等本次事务提交之后才能执行。这样我们可以保证当前的数据不会被其它事务修改。

上面我们提到,使用 select…for update 会把数据给锁住,不过我们需要注意一些锁的级别,MySQL InnoDB默认行级锁。行级锁都是基于索引的,如果一条SQL语句用不到索引是不会使用行级锁的,会使用表级锁把整张表锁住,这点需要注意。

优点与不足

悲观并发控制实际上是“先取锁再访问”的保守策略,为数据处理的安全提供了保证。但是在效率方面,处理加锁的机制会让数据库产生额外的开销,还有增加产生死锁的机会;另外,在只读型事务处理中由于不会产生冲突,也没必要使用锁,这样做只能增加系统负载;还有会降低了并行性,一个事务如果锁定了某行数据,其他事务就必须等待该事务处理完才可以处理那行数

乐观锁

在关系数据库管理系统里,乐观并发控制(又名“乐观锁”,Optimistic Concurrency Control,缩写“OCC”)是一种并发控制的方法。它假设多用户并发的事务在处理时不会彼此互相影响,各事务能够在不产生锁的情况下处理各自影响的那部分数据。在提交数据更新之前,每个事务会先检查在该事务读取数据后,有没有其他事务又修改了该数据。如果其他事务有更新的话,正在提交的事务会进行回滚。乐观事务控制最早是由孔祥重(H.T.Kung)教授提出。

乐观锁( Optimistic Locking ) 相对悲观锁而言,乐观锁假设认为数据一般情况下不会造成冲突,所以在数据进行提交更新的时候,才会正式对数据的冲突与否进行检测,如果发现冲突了,则让返回用户错误的信息,让用户决定如何去做。

相对于悲观锁,在对数据库进行处理的时候,乐观锁并不会使用数据库提供的锁机制。一般的实现乐观锁的方式就是记录数据版本。

数据版本,为数据增加的一个版本标识。当读取数据时,将版本标识的值一同读出,数据每更新一次,同时对版本标识进行更新。当我们提交更新的时候,判断数据库表对应记录的当前版本信息与第一次取出来的版本标识进行比对,如果数据库表当前版本号与第一次取出来的版本标识值相等,则予以更新,否则认为是过期数据。

实现数据版本有两种方式,第一种是使用版本号,第二种是使用时间戳

//3.线索池线索

$retry = 0;while ($retry < 3) {

$query= SaleClueQueue::onWriteConnection()->select('id', 'updated_at', 'phone', 'sc_business_type_id', 'sc_ids', 'sc_main_id', 'created_at')->whereIn('operator', [0, $userId])->where('next_call_time', '<=', date('Y-m-d H:i:s', time()))->where('is_double_appoint', $type);if ($type ==self::DOUBLE) {

$query->whereIn('city_id', SaleClueUtils::getMyCities());

}

$commonclue= $query->orderBy('weight', 'asc')->orderBy('created_at', 'desc')->first();if (!empty($commonclue)) {

$updateData=['appoint_status' =>AppointCallVars::APPOINT_STATUS_CALLING,'operator' => Utils::getInstance()->getUserId(),'updated_at' => date('Y-m-d H:i:s'),

];

$flag= SaleClueQueue::where('id', $commonclue->id)->where('updated_at', $commonclue->updated_at)->update($updateData);if($flag) {

$log= self::$logPress . '申请到公共线索 : 结果 :'. json_encode($commonclue);

LogUtils::logInfo($log);break;

}else{

$retry++;

}

}else{

$retry++;

}

}

数据库的字段

`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',

`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',

其间如果有其他对该记录做修改或加排他锁的操作,都会等待我们解锁或直接抛出异常。

mysql如何使用乐观锁_mysql 乐观锁和悲观锁相关推荐

  1. mysql默认使用悲观锁_mysql乐观锁和悲观锁详解

    mysql乐观锁和悲观锁详解 相信很多朋友在面试的时候,都会被问到乐观锁和悲观锁的问题,如果不清楚其概念和用法的情况下,相信很多朋友都会感觉很懵逼,那么面试的结果也就不言而喻了. 那么乐观锁和悲观锁到 ...

  2. 【Java锁体系】一、悲观锁和乐观锁

    目录: [Java锁体系]一.悲观锁和乐观锁 [Java锁体系]二.Java中的CAS机制算法 [Java锁体系]三.自旋锁详解 [Java锁体系]四.Synchronized关键字详解 [Java锁 ...

  3. mysql怎么加乐观锁和悲观锁_mysql - 乐观锁和悲观锁

    乐观锁 总是认为不会产生并发问题,每次去取数据的时候总认为不会有其他线程对数据进行修改,因此不会上锁,但是在更新时会判断其他线程在这之前有没有对数据进行修改,一般会使用版本号机制或CAS操作实现. 例 ...

  4. mysql version 乐观锁_mysql乐观锁总结和实践

    本文为转载. 原博客地址为: http://chenzhou123520.iteye.com/blog/1863407 上一篇文章<MySQL悲观锁总结和实践>谈到了MySQL悲观锁,但是 ...

  5. mysql如何使用乐观锁_mysql 乐观锁实现

    一.为什么需要锁(并发控制)? 在多用户环境中,在同一时间可能会有多个用户更新相同的记录,这会产生冲突.这就是著名的并发性问题. 典型的冲突有: 1.丢失更新:一个事务的更新覆盖了其它事务的更新结果, ...

  6. innodb 悲观锁 乐观锁_mysql乐观锁、悲观锁、共享锁、排它锁、行锁、表锁

    mysql乐观锁.悲观锁.共享锁.排它锁.行锁.表锁 乐观锁 总是假设最好的情况,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使 ...

  7. 关抢占 自旋锁_互斥锁、自旋锁、读写锁、悲观锁、乐观锁的应用场景

    前言 生活中用到的锁,用途都比较简单粗暴,上锁基本是为了防止外人进来.电动车被偷等等. 但生活中也不是没有 BUG 的,比如加锁的电动车在「广西 - 窃·格瓦拉」面前,锁就是形同虚设,只要他愿意,他就 ...

  8. 华为应用锁退出立即锁_面试官:你说说互斥锁、自旋锁、读写锁、悲观锁、乐观锁的应用场景...

    前言 生活中用到的锁,用途都比较简单粗暴,上锁基本是为了防止外人进来.电动车被偷等等. 但生活中也不是没有 BUG 的,比如加锁的电动车在「广西 - 窃·格瓦拉」面前,锁就是形同虚设,只要他愿意,他就 ...

  9. 面试官:你说说互斥锁、自旋锁、读写锁、悲观锁、乐观锁的应用场景?

    前言 生活中用到的锁,用途都比较简单粗暴,上锁基本是为了防止外人进来.电动车被偷等等. 但生活中也不是没有 BUG 的,比如加锁的电动车在「广西 - 窃·格瓦拉」面前,锁就是形同虚设,只要他愿意,他就 ...

最新文章

  1. 比特币区块链上最小的单位“聪” Satoshi STA 简介
  2. ORCFILE,ParquetFile,CubeFile使用场景区别
  3. 图形处理(十二)拉普拉斯网格优化、最小二乘网格模型光顺
  4. C#23种设计模式WebCast讲解笔记大全(25讲)
  5. python中+和join()的区别
  6. echarts散点图搭配时间轴
  7. GeoServer地图开发解决方案(四):发布Web地图服务(WMS)篇
  8. 自学python考哪些证书-学python需要考证吗?考证有什么好处?
  9. winqsb替代软件linux,winqsb软件64位-运筹学软件winqsb下载 v3.0免费版 附使用教程-下载啦...
  10. python爬虫实例1:获取一个网页的列表数据
  11. UE5——材质学习笔记(4):溶解材质
  12. 对话张冬洪 | 全面解读NoSQL数据库Redis的核心技术与应用实践
  13. ie 无人操作自动关闭_为什么ie11打开未响应然后闪退_win10ie打开就未响应自动关闭的解决方法...
  14. 分析无线遥控器信号并制作Hack硬件进行攻击
  15. 4步彻底关闭win10的自动更新功能
  16. SQL Server跟踪(Trace)--系统跟踪日志;从小白到大神,文章细节满满,细致到令人发指。
  17. Excel统一添加前缀与后缀
  18. 观成科技荣获中国网络安全产业联盟 “先进会员单位”并晋升理事单位
  19. 51nod 3199 操作栈
  20. appium重启报错:Could not proxy command to the remote server. Original error: socket hang up

热门文章

  1. what is IMHO?
  2. Java NIO - IO多路复用
  3. SSM整合(Spring、SpringMVC、MyBatis、Thymeleaf)
  4. 身体确实是革命的本钱
  5. Opencv训练自己分类器
  6. echarts 网格属性_echarts 绘制网格 教你使用graphic
  7. 程序员怎么写简历?怎么挖掘自己的亮点,推销自己?
  8. Mysql进阶学习(七)联合查询与DML语言
  9. 社会消防安全培训之火场疏散逃生互动演练系统
  10. mybatis面试题