当前位置: 首页 > news >正文

MySQL锁(二) 共享锁与互斥锁

共享锁与排他锁

2.1 共享锁(S锁)

定义:一个事务已获取共享锁,当另一个事务尝试对具备共享锁的数据进行读操作时,可正常读;进行写操作时,会被共享锁排斥

共享锁的意思很简单,也就是不同事务之间不会排斥,可以同时获取锁并执行。但这里所谓的不会排斥,仅仅只是指不会排斥其他事务来读数据,但其他事务尝试写数据时,就会出现排斥性,举个例子理解:

事务 T1ID=18 的数据加了一个共享锁,此时事务 T2、T3 也来读取 ID=18 的这条数据,这时 T2、T3 是可以获取共享锁执行的;但此刻又来了一个事务T4,它则是想对 ID=18 的这条数据执行修改操作,此时共享锁会出现排斥行为,不允许 T4 获取锁执行。

MySQL 中,我们可以在SQL语句后加上相关的关键字来使用共享锁,语法如下:

SELECT ... LOCK IN SHARE MODE;
-- MySQL8.0之后也优化了写法,如下:
SELECT ... FOR SHARE;

这种通过在 SQL 后添加关键字的加锁形式,被称为显式锁,而实际上为数据库设置了不同的事务隔离级别后,MySQL 也会对 SQL 自动加锁,这种形式则被称之为隐式锁。

样例:做个关于共享锁的小测试,先打开两个cmd窗口并于 MySQL 建立连接

-- 窗口1:
-- 开启一个事务
begin;
-- 获取共享锁并查询 id=2 的数据
select * from bank_balance where id=2 lock in share mode;
-- 窗口2:
-- 开启一个事务
begin;
-- 获取共享锁并查询 id=2 的数据
select * from bank_balance where id=2 lock in share mode;-- 尝试修改id=2的数据
update bank_balance set balance=230 where id=2;

  • 当窗口1获取了共享锁,窗口2执行查询/读操作时 可获取共享锁、正常读;但当窗口2执行修改/写操作时 窗口2没反应、未执行成功。
  • 而当窗口1中事务A提交后,窗口2事务B的写操作才能继续往下执行。

由上可见,一个事务已获取共享锁,当另一个事务尝试对具备共享锁的数据进行读操作时,可正常读;进行写操作时,会被共享锁排斥。因此从这个实验中可以得知:共享锁也具备排他性,会排斥其他尝试写的线程,当有线程尝试修改同一数据时会陷入阻塞,直至持有共享锁的事务结束才能继续执行

2.2 排他锁(X锁)

上面简单的了解了共享锁之后,紧着来看看排他锁,排他锁也被称之为独占锁。

当一个线程获取到独占锁后,会排斥其他线程(进行读写操作),如若其他线程也想对共享资源/同一数据进行操作,必须等到当前线程释放锁并竞争到锁资源才行

值得注意的一点是:排他锁并不是只能用于写操作,对于一个读操作,咱们也可以手动地指定为获取排他锁,当一个事务在读数据时,获取了排他锁,那当其他事务来读、写同一数据时,都会被排斥。比如事务T1ID=18的这条数据加了一个排他锁,此时T2来加排他锁读取这条数据,T3来修改这条数据,都会被T1排斥。

MySQL中,可以通过如下方式显式获取独占锁:

SELECT ... FOR UPTATE;

测试:

当两个事务同时获取排他锁,尝试读取一条相同的数据时,其中一个事务就会陷入阻塞,直至另一个事务结束才能继续往下执行;

但是select * from bank_balance where id=2这种普通读 不会被阻塞,也就是另一个事务不获取排他锁读数据,而是以普通的方式读数据,这种方式则可以立刻执行,Why?是因为读操作默认加共享锁吗?并不是,因为你尝试加共享锁读这条数据时依旧会被排斥。

可以明显看到,第二个事务中尝试通过加共享锁的方式读取这条数据,依旧会陷入阻塞状态,那前面究竟是因为啥原因才导致的能读到数据呢?其实这跟另一种并发控制技术有关,即MVCC机制,详情可见 MVCC 原理分析、MySQL是如何解决幻读的。

增、删、改都会对数据添加X锁,在查询语句中使用for update也会添加X锁

S锁X锁
S锁×
X所××

2.3 MySQL锁的释放

在前面的测试中,每次都仅获取了锁,但好像从未释放过锁?其实MySQL中释放锁的动作都是隐式的,毕竟如果交给咱们来释放,很容易由于操作不当造成死锁问题发生。因此对于锁的释放工作,MySQL自己来干,就类似于JVM中的GC机制一样,把内存释放的工作留给了自己完成。

  • 但对于锁的释放时机,在不同的隔离级别中也并不相同,比如在“读未提交”级别中,是SQL执行完成后就立马释放锁;而在“可重复读”级别中,是在事务结束后才会释放。

如果完全按照数据库规范来实现RC隔离级别,为了保证其他事务可以读到未提交的数据,那就必须得在SQL执行完成后,立马释放掉锁,这时另一个事务才能读到SQL对应写的数据,但在InnoDB引擎中,它基于MVCC机制实现了该效果,为此,InnoDBRC级别中,SQL执行结束后并不会释放锁。

http://www.dtcms.com/a/289825.html

相关文章:

  • Filter快速入门 Java web
  • Compose笔记(三十七)--FilterChip
  • TVLT:无文本视觉-语言Transformer
  • c++ duiLib 显示一个简单的窗口
  • AMD处理器 5700G 矿卡RX580-8G 打英雄联盟怎么样
  • 洛谷 P10287 [GESP样题 七级] 最长不下降子序列-普及/提高-
  • 《P2680 [NOIP 2015 提高组] 运输计划》
  • 【66】MFC入门到精通——(CComboBox)下拉框选项顺序与添加顺序不一致
  • 前端静态资源免费cdn服务推荐
  • Dify极简部署手册
  • 30天打好数模基础-逻辑回归讲解
  • 7-大语言模型—指令理解:指令微调训练+模型微调
  • 【算法训练营Day15】二叉树part5
  • 编程研发工作日记
  • 050_Set接口(HashSet / TreeSet / LinkedHashSet)
  • 力扣面试150题--搜索插入位置
  • 某市公安局视频图像信息综合应用平台设计方案Word(446页)
  • AI产品经理面试宝典第40天:用户反馈处理与技术应用面试题与答法
  • 多校2+多校1的遗珠
  • 信道相关系数
  • 安装kali时出现“安装步骤失败“如何解决及后续软件安装
  • Python自动化测试项目实战
  • QT项目-仿QQ音乐的音乐播放器(第一节)
  • 什么是卡贴???
  • 国产电钢琴性价比实战选购指南
  • Python 虚拟环境与构建工具全景指南:功能介绍与对比分析
  • 基于Transformer的心理健康对话系统:从零构建AI心理咨询助手
  • 【全球甲烷估算模型】简化一箱模型(1-box model)
  • MySQL中的排序和分页
  • [simdjson] 实现不同CPU调度 | 自动硬件适配的抽象