/answer/127777478 https://www.slideshare.net/billkarwin/innodb-locking-explained-with-stick-figures 意向锁的作用 于是就有了意向锁。在意向锁存在的情况下,事务A必须先申请表的意向共享锁,成功后再申请一行的行锁。 在意向锁存在的情况下,上面的判断可以改成: step1:事务B判断表是否已被其他事务用表锁锁表 step2:事务B发现表上已经有其他事务的意向共享锁,说明表中有些行被共享行锁锁住了,因此,事务B申请表的写锁会被阻塞 注意:申请意向锁的动作是数据库完成的,就是说,事务A申请一行的行锁的时候,数据库会自动先开始申请表的意向锁,不需要我们程序员使用代码来申请。 意向锁分为:意向共享锁 IS LOCK 、意向排它锁 IX LOCK 官方说明: 1.Before a transaction can acquire an S lock on a row in table
2.1 意向锁2.1.1 意向锁的概念意向锁的存在是为了协调行锁和表锁的关系,用于优化InnoDB加锁的策略。意向锁的主要功能就是:避免为了判断表是否存在行锁而去全表扫描。 因此,意向锁是表级别的;2.1.2 意向锁的应用测试IS和IX之间是共享的,意向锁(共享和排他)和表级别的X锁是冲突的;测试数据:sql 代码解读复制代码drop table if exists test4 Tips:有了意向锁,在事务B申请整表的排它锁时,直接判断该表有没有意向锁即可(判断一次)。 发现该表已经被加上意向锁了,但是意向锁之间是兼容的,可以申请成功,之后事务B尝试申请表级别排它锁,申请锁失败,被阻塞;因为表级别的排它锁和意向锁是冲突的;需要注意的是,虽然表级别的排它锁和意向锁之间的冲突的 ,但是行级别的排它锁和意向锁之间却是兼容的;我们观察下面案例:【测试案例】测试意向锁和行级S/X锁是兼容的,并且所有的意向锁直接都是兼容的session-01session-02begin;begin;
Separate transactions that attempt to insert values of 5 and 6, respectively, each lock the gap between 假设有值为 4 和 7 的索引记录,现在有两个事务,分别尝试插入值为 5 和 6 的记录,在获得插入行的排他锁之前,每个事务使用插入意向锁锁定 4 和 7 之间的间隙,但是这两个事务不会相互阻塞,因为行是不冲突的 这就是插入意向锁。 3. 阻塞的原因在于,插入意向锁和排他锁之间是互斥的。 小结 总结一下: 插入意向锁虽然名字中有意向二字,但实际上是一个特殊的间隙锁。 插入意向锁之间不互斥。 插入意向锁和排他锁之间互斥。 好啦,有问题欢迎留言讨论。
当我们需要加一个排他锁时,需要根据意向锁去判断表中有没有数据行被锁定(行锁); (1)如果意向锁是行锁,则需要遍历每一行数据去确认; (2)如果意向锁是表锁,则只需要判断一次即可知道有没数据行被锁定,提升性能 所以,没有意向锁的时候,让行锁与表锁共存,就会带来很多问题。于是有了意向锁的出现,如q1的答案中,数据库不需要在检查每一行数据是否有锁,而是直接判断一次意向锁是否存在即可,能提升很多性能。 5、下图表示意向锁和共享锁、排他锁的兼容关系。 意思是 当事务A对某个数据范围(行或表)上了“某锁”后,另一个事务B是否能在这个数据范围上“某锁”。 (3)假设有一个记录索引包含键值4和7,不同的事务分别插入5和6,每个事务都会产生一个加在4-7之间的插入意向锁,获取在插入行上的排它锁,但是不会被互相锁住,因为数据行并不冲突。 本例子和插入意向锁无关:是Gap锁和排它锁的关系 例如test表存在若干数据的数据,先开始一个事务A,插入一条n=5的数据;(图中步骤1) 此时如果开始一个事务B,执行查询 select * from
2.1 意向锁 2.1.1 意向锁的概念 意向锁的存在是为了协调行锁和表锁的关系,用于优化InnoDB加锁的策略。意向锁的主要功能就是:避免为了判断表是否存在行锁而去全表扫描。 因此,意向锁是表级别的; 2.1.2 意向锁的应用 测试IS和IX之间是共享的,意向锁(共享和排他)和表级别的X锁是冲突的; 测试数据: drop table if exists test4; CREATE Tips:有了意向锁,在事务B申请整表的排它锁时,直接判断该表有没有意向锁即可(判断一次)。 ,发现该表已经被加上意向锁了,但是意向锁之间是兼容的,可以申请成功,之后事务B尝试申请表级别排它锁,申请锁失败,被阻塞;因为表级别的排它锁和意向锁是冲突的; 需要注意的是,虽然表级别的排它锁和意向锁之间的冲突的 ,但是行级别的排它锁和意向锁之间却是兼容的;我们观察下面案例: 【测试案例】 测试意向锁和行级S/X锁是兼容的,并且所有的意向锁直接都是兼容的 session-01 session-02 begin;
01 意向锁,解决的问题 成熟的数据库设计中,需要一个模块对资源的并发控制进行管理。意向锁就是实现资源并发控制管理的经典方式。在讨论它的概念与设计前,我们先举几个MongoDB的经典场景。 而意向锁协议,是一种对树形(层级)资源进行并发控制的协议。它由"操作约定"和"冲突矩阵"两部分组成,且看下文。 02 MongoDB中的意向锁的定义 MongoDb使用了简化版的意向锁协议,抛却了SIX状态,保留了 IS/IX/S/X四种锁状态。其冲突矩阵为: ? 03 Mongo中意向锁的实现 虽然意向锁的设计非常简洁,但是理论和工程实践上,我们至少还要考虑如下几点: 一个高并发读写的db中,IS/IX锁源源不断的加上来,且相互不冲突,在这种条件下,如何避免X锁的饿死 带着这两个问题,我们分析mongoDB 意向锁的实现。 整体结构 mongoDB中的意向锁实现主要在 lockmanager.cpp/lockstate.cpp两部分。
01 意向锁,解决的问题 成熟的数据库设计中,需要一个模块对资源的并发控制进行管理。意向锁就是实现资源并发控制管理的经典方式。在讨论它的概念与设计前,我们先举几个MongoDB的经典场景。 而意向锁协议,是一种对树形(层级)资源进行并发控制的协议。它由"操作约定"和"冲突矩阵"两部分组成,且看下文。 02 MongoDB中的意向锁的定义 MongoDb使用了简化版的意向锁协议,抛却了SIX状态,保留了 IS/IX/S/X四种锁状态。其冲突矩阵为: ? 03 Mongo中意向锁的实现 虽然意向锁的设计非常简洁,但是理论和工程实践上,我们至少还要考虑如下几点: 一个高并发读写的db中,IS/IX锁源源不断的加上来,且相互不冲突,在这种条件下,如何避免X锁的饿死 带着这两个问题,我们分析mongoDB 意向锁的实现。 整体结构 mongoDB中的意向锁实现主要在 lockmanager.cpp/lockstate.cpp两部分。
为了解决这个问题,就引出了我们今天的意向锁。为了使多粒度级别的锁定变得实用,InnoDB 使用了意向锁,注意,意向锁是一种表级锁,它表示事务稍后对表中的行需要哪种类型的锁(共享或独占)。 意向锁也分为两类: intention shared lock:意向共享锁 (IS) 表示事务打算在表中的各个行上设置共享锁。 意向锁的加锁规则如下: 在事务可以获取表中行的共享锁之前,它必须首先获取表上的 IS 锁或更强的锁。 在事务可以获取表中行的排他锁之前,它必须首先获取表上的 IX 锁。 ,那么有没有办法让我们看到意向锁呢? 好啦,希望今天这篇文章能让小伙伴们对意向锁有一个简单的认知。
innodb锁机制探究(三)---插入意向锁 之前的文章中,提到了插入意向锁,今天来说说这种类型的锁。 先来看官方文档中对于这个锁是怎么介绍的。 简单理解就是插入意向锁锁定了索引之间的间隙,但是插入意向锁之间没有互相阻塞。 DEFAULT CHARSET=utf8 1 row in set (0.00 sec) mysql :yeyztest 10:28:15>>insert into lock_test4 values (5,5 上面的例子只是展示了插入意向锁的存在,现在我们来看插入意向锁之间,关于不同的记录,他们没有相互影响,首先看表中的记录: mysql :yeyztest 12:00:29>>select * from lock_test4 ; +----+------+ | id | age | +----+------+ | 5 | 5 | | 9 | 9 | +----+------+ 2 rows in set
因此,MySQL引入了意向锁机制。意向锁是数据库管理系统中用于实现锁协议的一种机制,旨在处理不同锁粒度(如行锁和表锁)之间的并发性问题。 注意:意向锁并非直接用于锁定资源,而是用于通知其他事务,以避免它们在资源上设置不兼容的锁。意向锁并非由用户直接请求,而是由MySQL管理的。 当一个事务请求获取行级锁或表级锁时,MySQL会自动获取相应表的意向锁。 这样,其他事务在请求获取表锁时,就可以首先基于这个意向锁来发现是否已经有其他事务加过锁,并根据该锁的类型(意向共享锁/意向排他锁)来判断自己是否可以获取锁。 意向锁是一种表级锁,在触发意向锁的事务提交或回滚后会被释放。我正在参与2024腾讯技术创作特训营最新征文,快来和我瓜分大奖!
mysql插入意向锁的使用 1、插入意向锁是Gap锁,不是意向锁,是insert操作产生的。当多个事务同时将不同的数据写入同一个索引间隙时,不需要等待其他事务完成,也不会发生锁等待。 假定有一个记录索引包含键值4和7,不同的事务分别插入5和6,每个事务都会产生一个插入意向锁,加到4-7之间,得到插入行上的排他锁,但不会相互锁定,因为数据行并不冲突。 2、插入意向锁不会阻止任何锁,插入记录会持有记录锁。 `test_user` trx id 117851203 插入意向锁 lock_mode X insert intention waiting Record lock, heap no 1 PHYSICAL n_fields 1; compact format; info bits 0 0: len 8; hex 73757072656d756d; asc supremum;; 以上就是mysql插入意向锁的使用
除此之外还有意向共享锁和意向排他锁,我将会在后面的意向锁中讲到 锁模式 下面是从模式上来划分,既然刚刚提到意向锁,那么我们就来西索一下意向锁吧 意向锁 意向锁属于表级锁,其设计目的主要是为了在一个事务中揭示下一行将要被请求锁的类型 即:意向锁是有数据引擎自己维护的,用户无法手动操作意向锁,在为数据行加共享 / 排他锁之前,InooDB 会先获取该数据行所在在数据表的对应意向锁。 光说肯定不懂,看示例 number 1 2 3 4 5 ==6== ==6== ==6== 11 id 1 3 5 7 9 10 11 12 23 假如我们这里有一个select select * from table where number = 6 for update; 那么这里会在(5,11)间加锁,其他事务再想 插入意向锁 插入意向锁是一种间隙锁形式的意向锁,在真正执行 INSERT 操作之前设置。
上面是从死锁日志中摘出来的一小段,从这段日志可以看到,事务 1(250489)持有 <i1 = 5, id = 23> 的记录的排他 Next-Key 锁,等待获得这条记录的插入意向锁。 = 23> 的记录加插入意向锁。 获得插入意向锁之后,插入 <i1 = 2, id = 25> 的记录到 <i1 = 5, id = 23> 的记录前面。 ,事务 1(250489)想要对这条记录加插入意向锁,也需要等待。 事务 1 等待事务 2 获得并释放锁之后,才能获得插入意向锁。 4.
很明显这是一个效率很差的做法,但是有了意向锁之后,情况就不一样了: 意向锁的兼容互斥性 意向锁是怎么解决这个问题的呢?首先,我们需要知道意向锁之间的兼容互斥性: ? 意向锁的并发性 这就牵扯到我前面多次强调的一件事情: 意向锁不会与行级的共享 / 排他锁互斥!!!意向锁不会与行级的共享 / 排他锁互斥!!!意向锁不会与行级的共享 / 排他锁互斥!!! 最后事务 C 也想获取 users 表中某一行的排他锁: SELECT * FROM users WHERE id = 5 FOR UPDATE; 事务 C 申请 users 表的意向排他锁。 因为意向锁之间并不互斥,所以事务 C 获取到了 users 表的意向排他锁。 因为id 为 5 的数据行上不存在任何排他锁,最终事务 C 成功获取到了该数据行上的排他锁。 意向锁在保证并发性的前提下,实现了行锁和表锁共存且满足事务隔离性的要求。 来源:Gtaker https://juejin.im/post/5b85124f5188253010326360
聊正题 聊完闲篇,咱们说回正题:什么是意向锁?为什么需要意向锁? PS:这里没意向书什么事啊,标题中有,纯粹是为了好玩。他们不能说没有什么关系,那是一点关系都没有。 定义 意向锁(Intention Locks)是 MySQL InnoDB 引擎中的一种锁机制(表级锁),用于协调事务间的加锁操作,以避免冲突和死锁的发生。 为什么要有意向锁? 为了避免这个问题,所以 MySQL 引入了意向锁,在事务 A 添加行锁的时候,先添加意向锁,而事务 B 在添加表锁的时候,先判断一下意向锁,如果有意向锁了,它就不能加表锁了,这样避免了锁冲突,提升了加锁判断的效率 想想一下,如果没有意向锁的话,那么事务 B 在加表锁的时候,只能一行行的判断有没有行锁,而这种判断的效率是非常低的,尤其数据量比较大时。 意向锁分类 意向锁分为以下两种类型: 意向共享锁(Intention Shared lock,IS):表示在某个资源上设置共享锁。
聊正题 聊完闲篇,咱们说回正题:什么是意向锁?为什么需要意向锁? PS:这里没意向书什么事啊,标题中有,纯粹是为了好玩。他们不能说没有什么关系,那是一点关系都没有。 定义 意向锁(Intention Locks)是 MySQL InnoDB 引擎中的一种锁机制(表级锁),用于协调事务间的加锁操作,以避免冲突和死锁的发生。 为什么要有意向锁? 为了避免这个问题,所以 MySQL 引入了意向锁,在事务 A 添加行锁的时候,先添加意向锁,而事务 B 在添加表锁的时候,先判断一下意向锁,如果有意向锁了,它就不能加表锁了,这样避免了锁冲突,提升了加锁判断的效率 想想一下,如果没有意向锁的话,那么事务 B 在加表锁的时候,只能一行行的判断有没有行锁,而这种判断的效率是非常低的,尤其数据量比较大时。 意向锁分类 意向锁分为以下两种类型: 意向共享锁(Intention Shared lock,IS):表示在某个资源上设置共享锁。
MySQL InnoDB锁:共享/排他锁,意向锁,插入意向锁。 今天介绍InnoDB七种锁的其中三种:共享/排他锁,意向锁,插入意向锁。 S锁,读读可以并行; (2)而只有一个事务可以拿到X锁,写写/读写必须互斥; 共享/排它锁的潜在问题是,不能充分的并行,解决思路是数据多版本,具体思路在《MySQL,InnoDB的高并发,MVCC(第5讲 二,意向锁(Intention Locks) InnoDB支持多粒度锁(multiple granularity locking),它允许行级锁与表级锁共存,实际应用中,InnoDB使用的是意向锁。 意向锁有这样一些特点: (1)首先,意向锁,是一个表级别的锁(table-level locking); (2)意向锁分为: - 意向共享锁(intention shared lock, IS),它预示着 (5)额,既然意向锁之间都相互兼容,那其意义在哪里呢?
假设存在值为 4 和 7 的索引记录,尝试插入值 5 和 6 的两个事务,在获取插入行上的排它锁之前,使用插入意向锁锁定间隙,即在(4,7)上加 gap lock。 但是这两个事务不会互相冲突等待。 简单来说,插入意向锁的属性为: 它不会阻塞其他任何锁; 它本身仅会被gap lock阻塞 2.3 INSERT到底有几把锁 1)普通INSERT 先加插入意向锁,插入意向锁之间不冲突。 比如4,7两行之间,可以同时插入5、6两行。 插入成功后,加对应行锁。 这时候,session A 持有索引 c 上的 (5,10]共享 next-key 读锁,所以session B插入时也被阻塞了。 next-key lock会退化为行锁,如果不是唯一索引,需要访问到第一个不满足条件的值,此时next-key lock会退化为间隙锁 范围查询:无论是否是唯一索引,范围查询都需要访问到不满足条件的第一个值为止 5、
InnoDB DEFAULT CHARSET=utf8; 隔离级别为RR 数据库版本5.7.20 插入数据 insert into test(alias,age) values(1,1),(3,3),(5,5 (Insert Intention Lock) 插入意向锁是为了提供并发插入的性能,也是一种间隙锁, 多个事务 同时写入 不同数据 至同一索引范围(区间)内,并不需要等待其他事务完成,不会发生锁等待 同时插入意向锁是会被 gap锁锁住的,在持有gap锁的情况下,新insert插入到这个范围时会获取这个范围的插入意向锁,此时如果这个范围有gap锁,则会阻塞当前插入,同时因为阻塞的插入意向锁,所以不会对后续相关的insert 进行额外阻塞 MySQL45讲说 所以我个人理解RR就是通过gap锁锁住插入意向锁来避免幻读的,这块大神有不同见解的话欢迎指导一下 3、本案例如何形成的死锁 1、锁兼容性 兼容性(获取/持有) Gap 11,所以意向锁被阻塞,等待中 T4时间事务1提交,gap锁释放 此时事务2的意向锁被事务3持有的gap锁锁住,事务3的意向锁被事务2持有的gap锁锁住,因此形成死锁,事务3回滚 这里需要注意的几点
我们看下意向锁如果提升表级锁的加锁效率。意向锁可以分为两类共享意向锁-IS:指示事务将对表中的各行施加共享锁。排它意向锁-IX:指示事务将对表中的各行施加排它锁。 什么时候会设置意向锁当一个事务要对表中的行设置共享锁时,它需要先对这个表施加共享意向锁或者排它意向锁。 当一个事务要对标中的行设置排它锁时,它需要先对这个表施加排它意向锁意向锁和表级共享/排它锁的兼容性如下表所示图片虽然意向锁是表级锁,但是因为施加行锁前需要先设置表级意向锁,因此意向锁不仅影响了表级锁的设置过程 具体的影响可以小结为以下3点对其它意向锁设置过程的影响:意向锁之间都是互相兼容的。也就是说,一个事务对表施加了意向锁,并不会阻塞其他事务对该表施加任意一种意向锁。 , (5, +∞);InnoDB使用临键锁来防止幻读。