【行锁及其算法、死锁、意向锁】

简介: 【行锁及其算法、死锁、意向锁】

文章目录

InnoDB 行锁的3种算法

InnoDB存储引擎有3种行锁的算法,其分别是:

❑Record Lock:单个行记录上的锁

❑Gap Lock:间隙锁,锁定一个范围,但不包含记录本身

❑Next-Key Lock∶Gap Lock+Record Lock,锁定一个范围,并且锁定记录本身

Record Lock总是会去锁住索引记录,如果InnoDB存储引擎表在建立的时候没有设置任何一个索引,那么这时 InnoDB存储引擎会使用隐式的主键来进行锁定。 Next-Key Lock是结合了Gap Lock和Record Lock的一种锁定算法,在Next-Key Lock算法下,InnoDB对于行的查询都是采用这种锁定算法。

在InnoDB 默认的事务隔离级别下,即REPEATABLE READ下,InnoDB存储引擎采用Next-Key Locking这种锁定 算法。例如一个索引有10,11,13和20这四个值,那么该索引可能被Next-Key Locking的区间为: (-∞,10] (10,11] (11,13] (13,20] (20,+∞)

当查询的索引含有唯一属性时,InnoDB存储引擎会对Next-Key Lock进行优化,将其降级为 Record Lock,即仅锁住索引本身,而不是范围。 什么是唯一属性,其实就是我们所说的能够标识该行数据唯一的标识。 unique 字段。比如:主键就是唯一的,不重复的。我们也可以自己设计多个字段组合不重 复,唯一的。

DROP TABLE IF EXISTS t;
CREATE TABLE t(a INT PRIMARY KEY);
INSERT INTO t SELECT 1;
INSERT INTO t SELECT 2;
INSERT INTO t SELECT 5;

表t共有1、2、5三个值。在上面的例子中,在会话A中首先对a=5进行X锁定。而由于a是主 键且唯一,因此锁定的仅是5这个值,而不是(2,5)这个范围,这样在会话B中插入值4而不 会阻塞,可以立即插入并返回。即锁定由Next-Key Lock算法降级为了Record Lock,从而提高应用的并发性。

CREATE TABLE z(a INT,b INT, PRIMARY KEY(a),KEY(b));
INSERT INTO z SELECT 1,1;
INSERT INTO z SELECT 3,1;
INSERT INTO z SELECT 5,3;
INSERT INTO z SELECT 7,6;
INSERT INTO z SELECT 10,8;

表z的列b是辅助索引,若在会话A中执行下面的SQL语句: SELECT * FROM z WHERE b=3 FOR UPDATE 很明显,这时SQL语句通过索引列b进行查询,该列不是唯一属性,因此其使用传统的Next-Key Locking技术加锁,并且由于有两个索引,其需要分别进行锁定。对于聚集索引(primay-key a),其仅对列a等于5的索引加 上Record Lock。而对于辅助索引b,其加上的是Next- Key Lock,锁定的范围是(1,3)。特别需要注意的是, InnoDB存储引擎还会对辅助索引下一个键值加上gap lock,即还有一个辅助索引范围为(3,6)的锁。

SELECT * FROM z WHERE a = 5 LOCK IN SHARE MODE;
INSERT INTO z SELECT 4,2;
INSERT INTO Z SELECT 6,5;

第一个SQL语句不能执行,因为在会话A中执行的 SQL语句已经对聚集索引中列a=5的值加上X锁,因 此执行会被阻塞。

第二个SQL语句,主键插入4,没 有问题,但是插入的辅助索引值2在锁定的范围(1, 3)中,因此执行同样会被阻塞。第三个SQL语句, 插入的主键6没有被锁定,5也不在范围(1,3)之间。 但插入的值5在另一个锁定的范围(3,6)中,故同样 需要等待。

InnoDB 行锁 next-key lock 有什么作用

在默认的事务隔离级别下,即REPEATABLE READ下,InnoDB存储引擎采用Next-Key Locking机制来避免 Phantom Problem(幻读问题,也称不可重复读)。Phantom Problem是指在同一事务下,连续执行两次同 样的SQL语句可能导致不同的结果。(在 READ COMMITTED 事务隔离级别下会出现)

CREATE TABLE z(a INT,b INT, PRIMARY KEY(a),KEY(b));
INSERT INTO z SELECT 1,1;
INSERT INTO z SELECT 3,1;
INSERT INTO z SELECT 5,3;
INSERT INTO z SELECT 7,6;
INSERT INTO z SELECT 10,8;

在同一事务中,若此时执行语句: SELECT*FROM z WHERE b=3 FOR UPDATE 两次,中间间隔10秒时间执行。可以肯 定的说,我们会得到第三行数据的结果,即 (5,3)。此时我们知道,会有一个 Record Lock锁定主键 5,还会有一个 gap lock锁定 (1,3)和 (3,6)。

假设:我们分析下,若此时没有gap lock(1,3)和 (3,6),如果只有Record Lock锁定主键 5 会不会造成幻读。 分析:我们在第一次 select 完成之后,第二次select 之前,插入一天数据: INSERT INTO z SELECT 20,3; 这条数据是可 以插入成功的,因为我们只有一个record lock 锁定了 主键5,对于新插入的数据主键为 20 ,可以插入,且 无重复。 插入完成后,第二次 select 得到了两个值,(5,3)(20,3)。这就造成了同一事物中,第一次读取和第二次 读取的结果不一样,出现幻读。 如果有gap lock,插入就会被阻塞,不会出现幻读。

死锁

如何预防数据库死锁,生产环境如何避免死锁 MySQL 篇 死锁是指两个或两个以上的事务在执行过程中,因争夺锁资源而造成的一种互相等待的现象。若无外力作用,事 务都将无法推进下去。解决死锁问题最简单的方式是不要有等待,将任何的等待都转化为回滚,并且事务重新开 始。毫无疑问,这的确可以避免死锁问题的产生。然而在线上环境中,这可能导致并发性能的下降,甚至任何一 个事务都不能进行。而这所带来的问题远比死锁问题更为严重,因为这很难被发现并且浪费资源。 解决死锁问题最简单的一种方法是超时,即当两个事务互相等待时,当一个等待时间超过设置的某一阈值时,其 中一个事务进行回滚,另一个等待的事务就能继续进行。在InnoDB存储引擎中,参数innodb_lock_wait_timeout用 来设置超时的时间。 超时机制虽然简单,但是其仅通过超时后对事务进行回滚的方式来处理,或者说其是根据FIFO的顺序选择回滚对 象。但若超时的事务所占权重比较大,如事务操作更新了很多行,占用了较多的undo log,这时采用FIFO的方式, 就显得不合适了,因为回滚这个事务的时间相对另一个事务所占用的时间可能会很多。 因此,除了超时机制,当前数据库还都普遍采用wait-for graph(等待图)的方式来进行死锁检测。较之超时的解 决方案,这是一种更为主动的死锁检测方式。InnoDB存储引擎也采用的这种方式。wait-for graph要求数据库保存以下两种信息: 锁的信息链表和事务等待链表。

事务T1指向T2边的定义为:

❑事务T1等待事务T2所占用的资源

❑事务T1最终等待T2所占用的资源,也就是事务之间在等待相同的资源,而事务T1发生在事务T2的后面

wait-for graph是一种较为主动的死锁检测机制,在每个事务请求锁并发生等待时都会判断是否存在回路,若存在则有死锁,通常来说InnoDB存储引擎选择回滚undo量最小的事务。

意向锁

InnoDB存储引擎支持多粒度(granular)锁定,这种锁定允许事务在行级上的锁和表级上的锁同时存在。 为了支持在不同粒度上进行加锁操作,InnoDB存储引擎支持一种额外的锁方式,称之为意向锁(Intention Lock)。 意向锁是将锁定的对象分为多个层次,意向锁意味着事务希望在更细粒度(fine granularity)上进行加锁 InnoDB存储引擎支持意向锁设计比较简练,其意向锁即为表级别的锁。设计目的主要是为了在一个事务中揭示下 一行将被请求的锁类型。其支持两种意向锁:

1)意向共享锁(IS Lock),事务想要获得一张表中某几行的共享锁

2)意向排他锁(IX Lock),事务想要获得一张表中某几行的排他锁

由于InnoDB存储引擎支持的是行级别的锁,因此意向锁其实不会阻塞除全表扫以外的任何请求。

InnoDB存储引擎实现了如下两种标准的行级锁:

❑共享锁(S Lock),允许事务读一行数据。

❑排他锁(X Lock),允许事务删除或更新一行数据。

如果一个事务T1已经获得了行r的共享锁,那么另外的事务T2可以立即获得行r的共享锁,因为读取并 没有改变行r的数据,称这种情况为锁兼容(Lock Compatible)。但若有其他的事务T3想获得行r的排 他锁,则其必须等待事务T1、T2释放行r上的共享锁——这种情况称为锁不兼容。

相关文章
|
存储 算法 关系型数据库
MySQL探秘(七):InnoDB行锁算法
在上一篇《InnoDB一致性非锁定读》中,我们了解到InnoDB使用一致性非锁定读来避免在一般的查询操作(SELECT FOR UPDATE等除外)时使用锁。然而锁这个事情是无法避免的,数据的写入,修改和删除都需要加锁。今天我们就继续学习InnoDB锁相关的知识。
|
1月前
|
算法 安全 数据安全/隐私保护
基于game-based算法的动态频谱访问matlab仿真
本算法展示了在认知无线电网络中,通过游戏理论优化动态频谱访问,提高频谱利用率和物理层安全性。程序运行效果包括负载因子、传输功率、信噪比对用户效用和保密率的影响分析。软件版本:Matlab 2022a。完整代码包含详细中文注释和操作视频。
|
9天前
|
算法 数据安全/隐私保护 索引
OFDM系统PAPR算法的MATLAB仿真,对比SLM,PTS以及CAF,对比不同傅里叶变换长度
本项目展示了在MATLAB 2022a环境下,通过选择映射(SLM)与相位截断星座图(PTS)技术有效降低OFDM系统中PAPR的算法实现。包括无水印的算法运行效果预览、核心程序及详尽的中文注释,附带操作步骤视频,适合研究与教学使用。
|
17天前
|
算法 数据挖掘 数据安全/隐私保护
基于FCM模糊聚类算法的图像分割matlab仿真
本项目展示了基于模糊C均值(FCM)算法的图像分割技术。算法运行效果良好,无水印。使用MATLAB 2022a开发,提供完整代码及中文注释,附带操作步骤视频。FCM算法通过隶属度矩阵和聚类中心矩阵实现图像分割,适用于灰度和彩色图像,广泛应用于医学影像、遥感图像等领域。
|
18天前
|
算法 调度
基于遗传模拟退火混合优化算法的车间作业最优调度matlab仿真,输出甘特图
车间作业调度问题(JSSP)通过遗传算法(GA)和模拟退火算法(SA)优化多个作业在并行工作中心上的加工顺序和时间,以最小化总完成时间和机器闲置时间。MATLAB2022a版本运行测试,展示了有效性和可行性。核心程序采用作业列表表示法,结合遗传操作和模拟退火过程,提高算法性能。
|
19天前
|
存储 算法 决策智能
基于免疫算法的TSP问题求解matlab仿真
旅行商问题(TSP)是一个经典的组合优化问题,目标是寻找经过每个城市恰好一次并返回起点的最短回路。本文介绍了一种基于免疫算法(IA)的解决方案,该算法模拟生物免疫系统的运作机制,通过克隆选择、变异和免疫记忆等步骤,有效解决了TSP问题。程序使用MATLAB 2022a版本运行,展示了良好的优化效果。
|
18天前
|
机器学习/深度学习 算法 芯片
基于GSP工具箱的NILM算法matlab仿真
基于GSP工具箱的NILM算法Matlab仿真,利用图信号处理技术解析家庭或建筑内各电器的独立功耗。GSPBox通过图的节点、边和权重矩阵表示电气系统,实现对未知数据的有效分类。系统使用MATLAB2022a版本,通过滤波或分解技术从全局能耗信号中提取子设备的功耗信息。
|
18天前
|
机器学习/深度学习 算法 5G
基于MIMO系统的SDR-AltMin混合预编码算法matlab性能仿真
基于MIMO系统的SDR-AltMin混合预编码算法通过结合半定松弛和交替最小化技术,优化大规模MIMO系统的预编码矩阵,提高信号质量。Matlab 2022a仿真结果显示,该算法能有效提升系统性能并降低计算复杂度。核心程序包括预编码和接收矩阵的设计,以及不同信噪比下的性能评估。
36 3
|
29天前
|
人工智能 算法 数据安全/隐私保护
基于遗传优化的SVD水印嵌入提取算法matlab仿真
该算法基于遗传优化的SVD水印嵌入与提取技术,通过遗传算法优化水印嵌入参数,提高水印的鲁棒性和隐蔽性。在MATLAB2022a环境下测试,展示了优化前后的性能对比及不同干扰下的水印提取效果。核心程序实现了SVD分解、遗传算法流程及其参数优化,有效提升了水印技术的应用价值。
|
1月前
|
机器学习/深度学习 算法 数据安全/隐私保护
基于贝叶斯优化CNN-LSTM网络的数据分类识别算法matlab仿真
本项目展示了基于贝叶斯优化(BO)的CNN-LSTM网络在数据分类中的应用。通过MATLAB 2022a实现,优化前后效果对比明显。核心代码附带中文注释和操作视频,涵盖BO、CNN、LSTM理论,特别是BO优化CNN-LSTM网络的batchsize和学习率,显著提升模型性能。
下一篇
无影云桌面