目录

  • 悲观锁
    • 悲观锁按使用性质分类
      • 共享锁(读锁、S锁)
      • 互斥锁(排它锁、独占锁、写锁、X锁)
      • 更新锁(U锁)
      • 自旋锁
    • 悲观锁按作用范围分类(按锁的粒度分类)
      • 行锁
      • 表锁
  • 乐观锁
    • 乐观锁的实现
      • 版本号
      • 待更新字段
  • 悲观锁的优缺点
  • 乐观锁的优缺点
  • 乐观锁与悲观锁的选择
  • 行锁的实现方式

数据库锁的种类一般分为两种:一种是悲观锁,一种乐观锁。

悲观锁

悲观锁(Pessimistic Lock)具有强烈的独占和排他特性,它指的是对数据被外界修改持保守态度,因此,在整个数据处理过程中,将数据处于锁定状态。悲观锁的实现,往往依靠数据库提供的锁机制。传统的关系数据库里用到了很多这种锁机制,比如行锁、表锁、读锁、写锁等,都是在操作之前先上锁

悲观锁的隔离级别可以看做可重复读

悲观锁按使用性质分类

共享锁(读锁、S锁)

事务A对对象T加共享锁,其他事务也只能对T加共享锁,多个事务可以同时读,但不能有写操作,直到A释放共享锁。

特点:多个事务可封锁同一个共享页;任何事务都不能修改该页;该页被读取完毕,共享锁立即被释放。

互斥锁(排它锁、独占锁、写锁、X锁)

事务A对对象T加互斥锁以后,其他事务不能对T加任何锁(即其他事物进入阻塞状态),只有事务A可以读写对象T直到A释放互斥锁。

特点:仅允许一个事务封锁此页;其他任何事务必须等到互斥锁被释放才能对该页进行访问;互斥锁一直到事务结束才能被释放。

更新锁(U锁)

更新锁用来预定要对此对象施加互斥锁,它允许其他事务读,但不允许再施加更新锁或互斥锁,当被读取的对象将要被更新时,则升级为互斥锁。

更新锁主要是用来防止死锁的,因为使用共享锁时,修改数据的操作分为两步,首先获得一个共享锁,读取数据,然后将共享锁升级为互斥锁,然后再执行修改操作。这样如果同时有两个或多个事务同时对一个对象申请了共享锁,在修改数据的时候,这些事务都要将共享锁升级为互斥锁。这些事务都不会释放共享锁而是一直等待对方释放,这样就造成了死锁。如果一个数据在修改前直接申请为更新锁,在数据修改的时候再升级为互斥锁,就可以避免死锁。

特点:用来预定要对此页施加互斥锁,它允许其他事务读,但不允许再施加更新锁或互斥锁;当被读取的页要被更新时,则升级为互斥锁。更新锁一直到事务结束时才能被释放。

自旋锁

自旋锁和互斥锁很像,一次只能有一个进程进入临界区,唯一不同的是自旋锁访问加锁资源时,会一直循环的查看是否释放锁。这样要比互斥锁效率高很多,但是仍然需要占用CPU

特点:自旋锁需要设定一个自旋等待的最大时间,如果持有锁的线程执行的时间超过自旋等待的最大时间扔没有释放锁,就会导致其它争用锁的线程在最大等待时间内还是获取不到锁,这时争用线程会停止自旋进入阻塞状态。除此之外,当自旋锁递归调用的时候会造成死锁现象,所以慎重使用自旋锁。

悲观锁按作用范围分类(按锁的粒度分类)

数据库能够确定那些行需要锁的情况下使用行锁,如果不知道会影响哪些行的时候就会使用表锁。

举个例子,一个用户表user,有主键id和用户生日birthday。当你使用update … where id=?这样的语句时,数据库明确知道会影响哪一行,它就会使用行锁;当你使用update … where birthday=?这样的的语句时,因为事先不知道会影响哪些行就可能会使用表锁。

行锁

行锁的作用范围是行级别,数据库能够确定那些行需要锁的情况下使用行锁,如果不知道会影响哪些行的时候就会使用表锁。举个例子,一个用户表user,有主键id和用户生日birthday当你使用update … where id=?这样的语句数据库明确知道会影响哪一行,它就会使用行锁,当你使用update … where birthday=?这样的的语句的时候因为事先不知道会影响哪些行就可能会使用表锁。

表锁

表锁的作用范围是整张表。

乐观锁

相对悲观锁而言,乐观锁机制采取了更加宽松的加锁机制,大多是基于版本号( Version )记录机制实现,而不需要借助数据库的锁机制。

乐观锁的实现

乐观锁的本质不是锁,其隔离级别可以看作为读未提交。乐观锁可以通过以下几种方式实现:

版本号

给数据增加一个版本标识,在数据库上就是表中增加一个version字段,每次更新把这个字段加1。读取数据的时候把version读出来,更新的时候比较一开始读取的version和现在的version,如果还是开始读取的version就可以更新了,如果现在的version比老的version大,说明有其他事务更新了该数据,并增加了版本号,这时候得到一个无法更新的通知,用户自行根据这个通知来决定怎么处理,比如重新开始一遍。

基于版本号实现乐观锁的关键是判断version和更新两个动作需要作为一个原子单元执行,否则在你判断可以更新以后正式更新之前有别的事务修改了version,这个时候你再去更新就可能会覆盖前一个事务做的更新。所以你可以使用update … where … and version=”old version”这样的语句,根据返回结果是0还是非0来得到通知,如果是0说明更新没有成功,因为version被改了,如果返回非0说明更新成功。

待更新字段

基于待更新字段实现乐观锁的方式和版本号方式相似,只是不增加额外字段,直接使用有效数据字段做版本控制信息,因为有时候我们可能无法改变旧系统的数据库表结构。假设有个待更新字段叫count,先去读取这个count,更新的时候去比较数据库中count的值是不是我期望的值(即开始读的值),如果是就把我修改的count的值更新到该字段,否则更新失败。

悲观锁的优缺点

悲观锁的优点是能避免冲突的发生。

悲观锁的缺点是开销较大,而且加锁时间较长,对于并发的访问性支持不好。

乐观锁的优缺点

乐观锁的优点是避免了长事务中的数据库加锁解锁开销,大大提升了大并发量下的系统整体性能表现。

乐观锁的缺点是只能在提交数据时才发现业务事务将要失败,如果系统的冲突非常的多,而且一旦冲突就要因为重新计算提交而造成较大的代价的话,乐观锁也会带来很大的问题。

乐观锁与悲观锁的选择

乐观锁适用于写比较少的情况下(多读场景),即冲突真的很少发生的时候,这样可以省去了锁的开销,加大了系统的整个吞吐量。

悲观锁适用于多写的场景,这种情况下一般会经常产生冲突。

行锁的实现方式

InnoDB 行锁是通过给索引上的索引项加锁来实现的。这种行锁意味着只有通过索引条件检索数据,InnoDB才使用行级锁,否则,InnoDB将使用表锁

MySQL数据库的锁详解相关推荐

  1. laravel 调试mysql_Laravel - MySQL数据库的使用详解3(Query Builder用法2:新增、修改、删除)...

    五.新增.修改.删除操作 在前文中我介绍了如何使用Query Builder(查询构造器)进行数据查询,下面接着介绍如何使用它进行数据的增.删.改操作.同样假设我们有如下用户表(user): 1,新增 ...

  2. MySQL 数据库 source 命令详解及实例

    MySQL 数据库 source 命令详解及实例 MySQL 数据库 source 命令,该命令是数据库导入命令.source 命令的用法非常简单,首先你需要进入 MySQL 数据库的命令行管理界面, ...

  3. linux系统——mysql数据库默认字符集详解

    linux系统--mysql数据库默认字符集详解 - mysql的字符集配置细化到四种 对数据库server配置 对库设置 对表设置 对列设置 - 对mysql-server设置 对server设置是 ...

  4. 17@MySQL数据库读现象详解(脏读、幻读、不可重复读)

    文章目录 MySQL数据库读现象 一.数据库的读现象 1.脏读(dirty read):读取未提交数据 [案列详解] 2.不可重复读取 (nonrepeatable read):前后多次读取,数据内容 ...

  5. dbeaver连接mysql 驱动jar_Jmeter(七) 从入门到精通 建立数据库测试计划实战lt;MySQL数据库gt;(详解教程)...

    1.简介 在实际工作中,我们经常会听到数据库的性能和稳定性等等,这些有时候也需要测试工程师去评估和测试,上一篇文章宏哥主要介绍了jmeter连接和创建数据库测试计划的过程,宏哥在文中通过示例和代码非常 ...

  6. mysql如何实现读提交锁_MySQL学习笔记(二)—MySQL事务及锁详解

    一.事务 数组库的一组操作,要么全部成功,要么全部失败 举例:银行转账 A账户向B账户转100 A账户余额扣去100 B账户余额增加100 上述两个操作要么全部成功,要么全部失败,部分成功或失败,数据 ...

  7. MySQL(六)InnoDB锁详解

    目录 InnoDB 锁的基本类型 锁的基本模式 共享锁(Shared Locks ) 排它锁(Exclusive Locks) 意向锁 锁的原理 锁的算法 记录锁 间隙锁 临键锁 总结​ 事务隔离级别 ...

  8. java连接mysql数据库方法_java连接mysql数据库的方法详解

    连接mysql数据库在java中有几种常用的方式有官方提供的JDBC连接MySQL数据库也有后面我们讲到的其它的方式连接数据库,具体如下. JDBC连接MySQL数据库 首先要下载Connector/ ...

  9. mysql数据库安装最详解

    数据库的基本概念 当今主流的数据库 SQL Server (微软公司产品) Oracle (甲骨文公司产品) DB2 (IBM公司产品) MySQL (甲骨文公司收购) 什么是mysql数据库 MyS ...

最新文章

  1. puppet 深入讲解
  2. Apache Storm 官方文档 —— 消息的可靠性保障
  3. 设计模式总结: 5种创建型,7种结构型,11种行为型
  4. MySQL添加服务、设置密码、修改密码
  5. python【5】-生成式,生成器
  6. 流量控制与拥塞控制区别
  7. SmartPDA图片
  8. 11 CO配置-控制-成本中心会计-定义分割结构
  9. 日出时的画面_如何拍摄日出日落,老摄影家近30年创作经验分享
  10. 社区成员提议YFI修改默认2%管理费为动态费用
  11. 阿里巴巴战略投资苏宁体育!
  12. gsonformat java代码_插件GsonFormat快速實現JavaBean
  13. python调用hownet API计算两个词的相似度
  14. 期末作业面向对象程序设计(Java)“猜拳游戏”
  15. 金蝶K3WISE 销售订单序时簿即时库存的开发
  16. [微软苏州校招 Hihocoder] Disk Storage
  17. Gitlab Code Review
  18. prometheus-预警-6
  19. CPU内存乱序访问与内存屏障
  20. 艾司博讯:在拼多多开店都有什么步骤

热门文章

  1. HR必看!设置员工生日提醒
  2. aardio - 【库】简单信息框
  3. 从图片中(批量)提取化学/分子结构——使用python进行批量提取(代码示例)
  4. PSO | 基础概念+两个简单的案例
  5. 东南亚LAZADA现在好做吗?
  6. 华为mate40和华为mate30的区别 华为mate40和华为mate30参数配置对比
  7. 明码(蛇皮解法)——第九届蓝桥杯C语言B组(省赛)第二题
  8. mysql groupadd_MySQL_linux mysql 安装与操作,复制代码 代码如下:groupadd mysql - phpStudy...
  9. 联盟训练在游戏AI多样化的探索
  10. Android面向切面AspectJ