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

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.xdnf.cn/news/15826.html

相关文章:

  • PHPStorm携手ThinkPHP8:开启高效开发之旅
  • 【华为机试】23. 合并 K 个升序链表
  • Leetcode 06 java
  • LeetCode 121. 买卖股票的最佳时机
  • 试用SAP BTP 02:试用SAP HANA Cloud
  • 算法分析--时间复杂度
  • Hadoop小文件合并技术深度解析:HAR文件归档、存储代价与索引结构
  • Function Callingの进化路:源起篇
  • gradle关于dependency-management的使用
  • 【实证分析】会计稳健性指标分析-ACF、CScore、Basu模型(2000-2023年)
  • 贝叶斯分类器的相关理论学习
  • Qwen3-8B 的 TTFT 性能分析:16K 与 32K 输入 Prompt 的推算公式与底层原理详解
  • 乐观锁实现原理笔记
  • 【论文阅读笔记】RF-Diffusion: Radio Signal Generation via Time-Frequency Diffusion
  • 考研最高效的准备工作是什么
  • 力扣面试150(34/150)
  • 隧道无线调频广播与“群载波”全频插播技术在张石高速黑石岭隧道中的应用
  • 44.sentinel授权规则
  • 【Java多线程-----复习】
  • 04训练windows电脑低算力显卡如何部署pytorch实现GPU加速
  • 标准制修订管理系统:制造业高质量发展的关键支撑
  • 【Java学习|黑马笔记|Day18】Stream流|获取、中间方法、终结方法、收集方法
  • python 装饰器的类型提示讲解
  • 下载win10的方法
  • Hiredis 构建 Redis 命令实战指南
  • 操作系统总结
  • XSS GAME靶场
  • 网络原理——IP
  • 深度神经网络原理学习记录
  • 微服务雪崩防护最佳实践之sentinel