前言:

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

一.悲观锁(Pessimistic Lock)

悲观锁的特点是先获取锁,再进行业务操作,即“悲观”的认为获取锁是非常有可能失败的,因此要先确保获取锁成功再进行业务操作。

通常所说的“一锁二查三更新”即指的是使用悲观锁。通常来讲在数据库上的悲观锁需要数据库本身提供支持,即通过常用的select … for update操作来实现悲观锁。

当数据库执行select for update时会获取被select中的数据行的行锁,因此其他并发执行的select for update如果试图选中同一行则会发生排斥(需要等待行锁被释放),

因此达到锁的效果。select for update获取的行锁会在当前事务结束时自动释放,因此必须在事务中使用。

这里需要注意的一点是不同的数据库对select for update的实现和支持都是有所区别的,例如oracle支持select for update no wait,表示如果拿不到锁立刻报错,而不是等待,

mysql就没有no wait这个选项。另外mysql还有个问题是select for update语句执行中所有扫描过的行都会被锁上,这一点很容易造成问题。

因此如果在mysql中用悲观锁务必要确定走了索引,而不是全表扫描。

二.乐观锁(Optimistic Lock)

乐观锁的特点先进行业务操作,不到万不得已不去拿锁。即“乐观”的认为拿锁多半是会成功的,因此在进行完业务操作需要实际更新数据的最后一步再去拿一下锁就好。

乐观锁在数据库上的实现完全是逻辑的,不需要数据库提供特殊的支持。一般的做法是在需要锁的数据上增加一个版本号,或者时间戳,然后按照如下方式实现:

1. SELECT data AS old_data, version AS old_version FROM …;
2. 根据获取的数据进行业务操作,得到new_data和new_version
3. UPDATE SET data = new_data, version = new_version WHERE version = old_version
if (updated row > 0) {
// 乐观锁获取成功,操作完成
} else {
// 乐观锁获取失败,回滚并重试
}

乐观锁是否在事务中其实都是无所谓的,其底层机制是这样:在数据库内部update同一行的时候是不允许并发的,即数据库每次执行一条update语句时会获取被update行的写锁,

直到这一行被成功更新后才释放。因此在业务操作进行前获取需要锁的数据的当前版本号,然后实际更新数据时再次对比版本号确认与之前获取的相同,并更新版本号,

即可确认这之间没有发生并发的修改。如果更新失败即可认为老版本的数据已经被并发修改掉而不存在了,此时认为获取锁失败,需要回滚整个业务操作并可根据需要重试整个过程。

三.总结

(1)乐观锁在不发生取锁失败的情况下开销比悲观锁小,但是一旦发生失败回滚开销则比较大,因此适合用在取锁失败概率比较小的场景,可以提升系统并发性能。

(2)乐观锁还适用于一些比较特殊的场景,例如在业务操作过程中无法和数据库保持连接等悲观锁无法适用的地方。

关于MySql悲观锁与乐观锁的更多相关文章

  1. mysql的锁--行锁,表锁,乐观锁,悲观锁

    一 引言--为什么mysql提供了锁 最近看到了mysql有行锁和表锁两个概念,越想越疑惑.为什么mysql要提供锁机制,而且这种机制不是一个摆设,还有很多人在用.在现代数据库里几乎有事务机制,aci ...

  2. Mysql锁机制--乐观锁 & 悲观锁

    Mysql 系列文章主页 =============== 从 这篇 文章中,我们知道 Mysql 并发事务会引起更新丢失问题,解决办法是锁.所以本文将对锁(乐观锁.悲观锁)进行分析. 第一部分 悲观锁 ...

  3. Mysql共享锁、排他锁、悲观锁、乐观锁及其使用场景

    一.相关名词 |--表级锁(锁定整个表) |--页级锁(锁定一页) |--行级锁(锁定一行) |--共享锁(S锁,MyISAM 叫做读锁) |--排他锁(X锁,MyISAM 叫做写锁) |--悲观锁( ...

  4. MySQL学习笔记(四)悲观锁与乐观锁

    恼骚 最近在搞并发的问题,订单的异步通知和主动查询会存在并发的问题,用到了Mysql数据库的 for update 锁 在TP5直接通过lock(true),用于数据库的锁机制 Db::name('p ...

  5. mysql 悲观锁与乐观锁的理解

    悲观锁与乐观锁是人们定义出来的概念,你可以理解为一种思想,是处理并发资源的常用手段. 不要把他们与mysql中提供的锁机制(表锁,行锁,排他锁,共享锁)混为一谈. 一.悲观锁 顾名思义,就是对于数据的 ...

  6. 谈谈MySQL支持的事务隔离级别,以及悲观锁和乐观锁的原理和应用场景?

    在日常开发中,尤其是业务开发,少不了利用 Java 对数据库进行基本的增删改查等数据操作,这也是 Java 工程师的必备技能之一.做好数据操作,不仅仅需要对 Java 语言相关框架的掌握,更需要对各种 ...

  7. 【MySQL锁】MySQL悲观锁和乐观锁概念

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

  8. mysql悲观锁与乐观锁

    简介 数据库管理系统(DBMS)中的并发控制的任务是确保在多个事务同时存取数据库中同一数据时不破坏事务的隔离性和统一性以及数据库的统一性. 用途 乐观锁和悲观锁是并发控制主要采用的技术手段.无论是悲观 ...

  9. 浅谈Mysql共享锁、排他锁、悲观锁、乐观锁及其使用场景

    浅谈Mysql共享锁.排他锁.悲观锁.乐观锁及其使用场景   Mysql共享锁.排他锁.悲观锁.乐观锁及其使用场景 一.相关名词 |--表级锁(锁定整个表) |--页级锁(锁定一页) |--行级锁(锁 ...

随机推荐

  1. IK 中文分词器

    链接:https://github.com/wks/ik-analyzerIKAnalyzer是一个开源的,基于java语言开发的轻量级的中文分词工具包.从2006年12月推出1.0版开始,IKAna ...

  2. [LeetCode&Python] Problem 169. Majority Element

    Given an array of size n, find the majority element. The majority element is the element that appear ...

  3. 测试那些事儿—浅谈TCP/IP协议

    TCP/IP协议是一系列网络协议的总和,是构成网络通信的核心骨架. TCP/IP的工作原理通俗的讲就是一个主机的数据要经过哪些过程才能发送到对方的主机上. TCP/IP协议采用四层结构,分别为应用层, ...

  4. 田螺便利店—win10专业版激活码

    win10专业版:VP4MG-CMX8Q-27THR-Y468R-HRVR7 开始——设置——更新和安全——激活——更改产品密钥 复制VP4MG-CMX8Q-27THR-Y468R-HRVR7即可激活 ...

  5. rest-framework之分页器

    rest-framework之分页器 本文目录 一 简单分页(查看第n页,每页显示n条) 二 偏移分页(在第n个位置,向后查看n条数据) 三 CursorPagination(加密分页,只能看上一页和 ...

  6. Windows 10瘦身

    Windows操作系统功能越来越强大,同时体型也越来越臃肿.安装盘没有60Gb都不敢安装.Windows10 安装最低磁盘要求20G ====瘦身基础篇,适合任何用户:(可见目录,简单迁移)1. 安装 ...

  7. C++学习(三十三)(C语言部分)之 队列

    队列测试代码笔记如下: #include<stdio.h> #define SIZE 10 typedef struct Queue { int data[SIZE]; //队列的容量 i ...

  8. 浅谈log4j-5-读取properties文件(转自godtrue)

    #### 在代码中配置log4j环境的方式,我们已经见识过了,是不是感觉比较麻烦,我们试试使用配置文件的方式是否使您的应用程序更加的灵活.# Log4j支持两种配置文件格式,一种是XML格式的文件,一 ...

  9. linux freopen函数

    编程之路刚刚开始,错误难免,希望大家能够指出. 有些需求需要我们不断的输入数据很庞大,如果我们安装常规方法不断地在终端输入值很麻烦(前提是输入的数据是固定的,并不会随程序的运行而改变),这个时候我们就 ...

  10. 05typedef struct用法详解与小结

    1.基本解释 typedef为C语言的关键字,作用是为一种数据类型定义一个新名字,这里的数据类型包括内部数据类型(int,char等)和自定义的数据类型(struct等). 在编程中使用typedef ...