MySQL中间隙锁的加锁机制

数据库隔离级别RC,什么场景会有间隙锁? 在RC(Read Committed,读已提交)隔离级别下,通常不会有间隙锁,因为间隙锁主要是为了解决可重复读(Repeatable Read,RR)隔离级别下的幻读问题而引入的。然而,在某些特殊场景下,RC级别下也可能出现类似间隙锁的行为,但这通常不是通过间隙锁直接实现的,而是可能与MySQL的锁机制、索引使用、以及特定版本的优化策略有关。 阅读详情
AI摘要

本文详细介绍了MySQL在可重复读(RR)隔离级别下,间隙锁的工作原理和作用,通过一系列实验展示了不同索引类型(主键、唯一、非唯一)下的加锁规则。实验涵盖了等值查询和范围查询,揭示了间隙锁如何避免幻读现象,并通过实际操作演示了加锁过程和锁冲突的情况,帮助读者深入理解MySQL的事务隔离与锁机制。


微信搜索“coder-home”或扫一扫下面的二维码,关注公众号,第一时间了解更多干货分享,还有各类视频教程资源。扫描它,带走我


背景

间隙锁是MySQL在RR可重复读隔离级别下用来修复幻读才引入的一种锁,间隙锁也只有在RR可重复读隔离级别下才会存在,如果是在RC读已提交隔离级别下,是没有间隙锁的存在的。另外,我们也知道,幻读这种现象也只有在当前读的时候才会发生,在一致性快照读的情况下是没有幻读现象的。

那么间隙锁到底是怎么样工作的?它是如何保证在当前读的时候,不会出现幻读现象的呢?接下来让我们一起剖解分享一下间隙的加锁的机制是怎么样的。

实验环境的准备

前置条件

接下来的实验是在如下的环境下开始的:

  • MySQL的版本:5.7.24
  • 事务的隔离级别:RR可重复读
  • 测试使用存储引擎为innodb存储引擎

准备建表语句

下面的实验使用的userinfo表结果如下表格所示:其中用户的年龄age字段是可能存在多个用户的年龄相同的情况,所以这个age列上有非唯一索引;而所有用户的手机号码不会重复,所以这个phone列上面有一个唯一索引;姓名name列和备注remark列上面没有任何索引就是两个普通的字段。

序号字段名称字段类型字段注释索引类型
1idint表的主键聚簇索引
2namevarchar姓名N/A
3ageint年龄非唯一索引
4phonevarchar手机号唯一索引
5remarkvarchar备注信息N/A

建表语句如下:

CREATE TABLE `userinfo` (
  `id` int(11) NOT NULL COMMENT '主键',
  `name` varchar(255) DEFAULT NULL COMMENT '姓名',
  `age` int(11) DEFAULT NULL COMMENT '年龄,普通索引列',
  `phone` varchar(255) DEFAULT NULL COMMENT '手机,唯一索引列',
  `remark` varchar(255) DEFAULT NULL COMMENT '备注',
  PRIMARY KEY (`id`),
  UNIQUE KEY `idx_userinfo_phone` (`phone`) USING BTREE COMMENT '手机号码,唯一索引',
  KEY `idx_user_info_age` (`age`) USING BTREE COMMENT '年龄,普通索引'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

准备初始化数据

下面实验中使用到的测试数据如下:

INSERT INTO `userinfo`(`id`, `name`, `age`, `phone`, `remark`) VALUES (0, 'mayun', 20, '0000', '马云');
INSERT INTO `userinfo`(`id`, `name`, `age`, `phone`, `remark`) VALUES (5, 'liuqiangdong', 23, '5555', '刘强东');
INSERT INTO `userinfo`(`id`, `name`, `age`, `phone`, `remark`) VALUES (10, 'mahuateng', 18, '1010', '马化腾');
INSERT INTO `userinfo`(`id`, `name`, `age`, `phone`, `remark`) VALUES (15, 'liyanhong', 27, '1515', '李彦宏');
INSERT INTO `userinfo`(`id`, `name`, `age`, `phone`, `remark`) VALUES (20, 'wangxing', 23, '2020', '王兴');
INSERT INTO `userinfo`(`id`, `name`, `age`, `phone`, `remark`) VALUES (25, 'zhangyiming', 38, '2525', '张一鸣');

最后的测试环境

准备好表和初始化数据之后,我们的测试环境就准备好了,最后的测试环境如下:
在这里插入图片描述

间隙锁的结构

针对上面我们准备表结构和插入的测试数据,目前userinfo表中有三个间隙锁,分别在主键id列上,非唯一索引age列,唯一索引phone列。它们的间隙锁的分布情况分别如下。根据各个索引列上面的值,把索引切分为不同的区间段。

  • 主键索引id列上的间隙锁结构如下图所示:
    在这里插入图片描述
  • 非唯一索引age列上的间隙锁结构如下所示:因为是非因为索引,所以索引中的值可以重复出现,所以在图中没有标记每一个间隙可能出现的值,用三个点代替显示。
    在这里插入图片描述
  • 唯一索引phone列上的间隙锁如下所示:
    在这里插入图片描述

我们要知道,MySQL中的行锁和间隙锁是锁定就是对应的索引。行锁锁定的行所在的主键索引,非主键索引列上面的锁也是锁定对应的非主键索引。间隙锁也是锁定索引,他们不是锁定行,也不是锁定某个列,是锁定对应的索引。

索引的结构

上面的表插入数据之后,在id主键索引上会有一个B+Tree的索引结构。在age非唯一索引和phone唯一索引两列上,会有两个B+Tree索引结构。他们的结构如下图所示:

  • id主键索引结构
    在这里插入图片描述

  • age非唯一索引结构
    在这里插入图片描述

  • phone唯一索引结构
    在这里插入图片描述

间隙锁加锁规则

这里先简单总结一下间隙锁加锁的一些规则,然后我们根据规则去逐步验证这些规则。

  1. 查询过程中访问到的对象才会加锁。
  2. 加锁的基本单位是next-key lock(前开后闭)。
  3. 等值查询上MySQL的优化:索引上的等值查询,如果是唯一索引,next-key lock会退化为行锁,如果不是唯一索引,需要访问到第一个不满足条件的值,此时next-key lock会退化为间隙锁。
  4. 范围查询:无论是否是唯一索引,范围查询都需要访问到不满足条件的第一个值为止。

实验部分

我们针对以下几个SQL语句来分析一下具体间隙锁的加锁的范围是什么。这几个SQL分别使用不同的列来作为where条件来筛选表中第2条数据。

根据where条件中各个列的类型,我们可以分为如下4类SQL。下面的四个语句都会自动给表增加上对应的行锁之外,如果有必要增加对应的间隙锁,也会增加上间隙锁来避免幻读的发生,而如果不需要间隙锁就可以避免幻读的发生,那么MySQL就不会自动增加上对应的间隙锁只要对应的行锁就可以了。

/*根据主键查询,给行增加X锁*/
select * from userinfo where id = 5 for update;

/*根据唯一索引列查询,给行增加X锁*/
select * from userinfo where phone = '5555' for update;

/*根据非唯一索引列查询,给行增加X锁*/
select * from userinfo where age = 23;

/*根据普通列查询,给行增加X锁*/
select * from userinfo where name = 'liuqiangdong';

实验的过程中,还需要密切观察下面三个表中的内容,这里记录的MySQL在执行期间正在允许的事务、锁、锁等待等信息。从这里三张表中,可以看到每一个阻塞是因为什么阻塞的,被哪些锁阻塞的。

/*查看正在运行的事务*/
select * from information_schema.innodb_trx;

/*查看当前的锁信息*/
select * from information_schema.innodb_locks;

/*查看锁等待的信息*/
select * from information_schema.innodb_lock_waits;

RR级别+主键索引列

在可重复读隔离级别下,通过主键索引去查询数据尝试增加X锁的时候,使用如下的SQL语句

/*根据主键查询,给行增加X锁*/
select * from userinfo where id = 5 for update;

此时会在主键索引上索引值为5的记录上增加X锁,此时不需要使用其他间隙锁就可以避免幻读的发生。因为主键索引是唯一索引,当锁住这一行数据后,其他事务将不能做如下操作:

  1. 不能删除id=5的这一行数据。id=5的行已经被当前事务给增加了X锁,所以其他事务将不能查询、修改、删除这一行数据。
  2. 不能新插入一个id=5的行。表中已经存在主键id=5的行了,所以其他事务不能再次增加一个id=5的行。所以就可以避免在id=5这个条件下再次查询的时候出现多行数据而产生幻读的现象。
  3. 不能修改id=5的这一行数据。id=5的行已经被当前事务给增加了X锁,所以其他事务将不能查询、修改、删除这一行数据。
  4. 不能把其他行的id值改为5。这一行是主键索引,也是唯一所以,它的值不能重复。所以其他事务不能把一个id!=5的行改为id=5的行。所以就可以避免在id=5这个条件下再次查询的时候出现多行数据而出现幻读的现象。

此时增加的锁也只有主键索引id=5这一个行锁,锁结构如下:
在这里插入图片描述

综上几点可以确定,当使用主键索引进行查询数据增加X锁的时候,是可以避免幻读的发生,此时不需要间隙锁的参与就可以避免幻读。其他事务可以正常的对userinfo表进行除id=5之外增删改查操作。比如插入一个id=6的数据行,删除id=0的数据行,修改id=20的行等操作。

实验截图:

通过如下的实验,可以看出,在左侧的事务给表userinfo增加了id=5的行锁之后,右侧的事务仍然可以对表中其他数据行和间隙进行增删改查。说明左侧的事务只增加了id=5的行锁,没有间隙锁的存在。
在这里插入图片描述

下面我们再来看一个因为索引失效而走全表扫描的例子,与此同时下面的这个例子也能从一定程度上说明左侧的事务只对id=5这一行增加了一个X锁,没有其他间隙锁或行锁的存在。
在这里插入图片描述

上面截图中的第5,6,7,8在尝试加S锁的时候,这里解释一下为什么成功,为什么失败。

  • 第5步中,是通过id=0这个条件去给id=0的这一行数据增加S共享锁,where条件中的id是主键列,也是一个唯一索引列,所以在查询的时候,可以直接通过主键索引定位到对应的行。所以直接找到了id=0的这一行,同时发现这一行上面没有其他X所存在,所以增加S锁成功。
  • 第6步中,是通过phone=0000这个条件去给id=0的行增加S锁,这里之所以失败的原因如下:
    1. phone是一个varchar类型的唯一索引,在给它赋值的时候,如果我们赋值不是varchar类型的数据,MySQL为了避免SQL直接出现错误,会尝试进行隐式转换,把数据库中的phone列使用函数转换为和你赋值的类型一致的数据再进行等值判断。
    2. 对索引列使用函数操作,会导致查询的时候不走索引,索引对当前查询SQL语句失效了,此时的phone的索引就不会被使用,所以此时在查询数据的时候就是走全表扫描。
    3. 在全表扫描的时候,扫描到第一个phone=0000的行并不会停止,因为此时phone列的唯一索引没有使用,所以要继续扫描,判断表中每一行的phone列的值是否为0000。根据前面说的加锁规则,在尝试加锁的时候,会对所有扫描过的对象增加对应的锁。所以在扫描到id=5的行的时候,尝试给这一行增加S锁。
    4. 然而,id=5的这一行的索引记录,已经被左侧的事务给增加了一个X锁,因为S锁和X锁不能共存,所以此时给id=5的索引记录加S锁失败。
    5. 所以步骤6就被阻塞住了,等超过事务默认的最大等待阈值就会退出。
  • 第7步中,执行成功了的原因正式因为我们在给phone列赋值的时候,使用了正确的varchar类型的'0000',所以在查询表中数据的时候,可以使用到唯一索引,直接定位到对应的主键索引上面的值,从而可以对id=0的索引记录加锁成功。不需要走全表扫描就可以找到对应的行。
  • 第8步中,被阻塞的原因是因为它要给id=5的索引记录增加S锁,它可以通过主键索引直接定位到要加S锁的索引记录行,不需要走全表扫描。找到id=5的行后尝试给它加S锁,但是发现这个行已经被左侧的事务给增加了X锁。S锁和X锁不能共存,所以右侧的事务给id=5的行增加S锁失败。

所以:在我们平时开发的时候,写SQL语句的时候,一定要格外的注意给where条件后面的字段赋值的时候,一定要根据对应的字段类型进行赋值。切不要让MySQL使用隐式转换的功能导致索引失效而走全表扫描。这样我们会有一种错觉:为啥我加了索引了,查询还是很慢。你要保证:增加了索引,并且SQL语句查询的时候真正使用到了索引,这样才会对你的SQL性能有提升。

RR级别+唯一索引列

当我们尝试通过一个唯一索引列去给表增加X锁的时候,会使用如下的SQL,它会给表增加那些锁呢?

/*根据唯一索引列查询,给行增加X锁*/
select * from userinfo where phone = '5555' for update;

此时查询数据的过程是这样的:先查唯一索引,然后再回表查询主键索引,然后从主键索引上返回查询的结果。具体流执行流程如下:

  • 先根据phone列上面的唯一索引找到索引值为’5555’索引记录,因为是唯一索引,所以找到5555的索引记录后就停止搜索了,索引树上只有一条5555的记录。
  • 然后再根据这个索引记录上面存储的主键索引的值5去主键索引上面查找需要查询的行记录。
  • 根据加锁规则中提到的:只会在扫描到的对象上增加锁。所以会在主键索引id=5的索引记录上增加X锁,也会在唯一索引phone='5555’的索引记录上增加一个X锁。

此时加锁的情况如下所示:
在这里插入图片描述

疑问1:如何证明通过select * from userinfo where phone='5555' for update增加X锁的时候,在索引列phone='5555’的索引记录上增加了X锁了?通过如下实验可以证明这个结论:
在这里插入图片描述

针对上图中的各个实验步骤,简单做如下说明。

  • 在第3步执行完成的之后,在非主键索引(非聚簇索引、二级索引)phone中的phone='5555’索引记录行增加了X锁,同时在主键索引(聚簇索引)id中id=5的索引记录行增加了X锁。
  • 第4步中查询语句使用了覆盖索引的功能,我们只查询的phone这一列的值,在非主键索引上就包含了我们要查询的结果,所以这个查询不会去查询主键索引,只会在非主键索引上搜索查找。但是它增加S锁和X锁都失败了,说明这个phone='5555’索引记录上已经被增加了X锁。
  • 在第5不执行完成后,左侧的事务就回滚了,所以在第3步中增加的两把X锁都被释放掉了。
  • 所以在第6步和第7步中,再次尝试给phone='5555’的非主键索引记录行增加S锁或X锁的时候,都加锁成功了。
  • 此时就已经说明了在通过非主键索引且是唯一索引列,在给表增加X锁的时候,除了会对主键索引对应的记录行增加X锁之外,还会在非聚簇索引的索引记录上增加X锁。
  • 在第11步中,我们做了和第3不类似的操作,但是和第3步的区别在于:此时我们给表增加的是S锁而不是第3步中的X锁。
  • 因为S锁和S锁是共享的,所以在右侧事务中的第12步中,给phone='5555’的索引记录增加S锁,成功。
  • 因为S锁和X锁不能共存,所以在右侧事务中的第13步中,给phone='5555’的索引记录增X锁,加锁失败。而当左侧事务执行完第14步回滚事务的操作之后,此时phone列上面的phone值为’5555’的索引记录的S锁已经被释放,所以做右侧事务中,再次尝试给phone='5555’的索引记录增加X锁,此时才成功。

疑问2:为什么要在主键索引id=5这个记录上也增加X锁?如果并发的一个SQL,是通过主键索引来删除数据,SQL语句为:delete from userinfo where id = 5;。 此时,如果update语句没有将主键索引上的记录加锁,那么并发的delete就会感知不到前面的update语句的存在,违背了同一记录上的更新/删除需要串行执行的原则。

疑问3:通过疑问2,我们知道在唯一索引phone上面增加了X锁,那么我们前面的实验一中,通过select * from userinfo where id = 5 for update增加X锁的时候,有没有在索引列phone='5555’的索引记录上增X锁呢?

我们的实验截图如下:
在这里插入图片描述

注意:目前我只能确定phone='5555’的索引记录上一定是没有X锁,但是有没有S锁目前还不能确定,因为如果通过id=5 for update加X锁后,如果在phone='5555’的非主键索引的索引记录上增加一个S锁,在右侧的事务中,也是可以获得S锁的,因为S锁和S锁是可以共存的。事实上,我们也确实在右侧的事务中获得了phone='5555’索引记录上的S锁。索引我不确定在左侧的事务中,是否给phone='5555’的索引记录上增加了S锁。

如果大家有办法可以证明这一点,也希望大家给我留言你的证明方式。

RR级别+非唯一索引列

通过非唯一索引列age来增加X锁的SQL语句如下,当执行完成如下语句之后,表userinfo会有哪些锁产生呢?

select * from userinfo where age = 23 for update;

加锁情况如下图所示:
在这里插入图片描述

这里需要说明几点:

  • 根据非唯一索引加锁规则,此次增加的间隙锁有:(20,23]、(23,27]。对于非唯一索引来说,当扫描到最后一个边界age=27的时候,临键锁退化为间隙锁。所以此时的锁为间隙锁:(20,27),不包含左右两边的边界值20和27。
  • 行锁有:在age=23的非主键索引记录上有两把,因为有两个age=23索引记录。同时在id=5和id=20的主键索引记录上也有两把X锁,
  • 只要当age的取值范围为(20,27)的时,任何记录行都不能插入成功。因为age上面的间隙锁阻止了数据的插入。
  • 只要当age的值不属于(20,27),且不等于20也不等于27的时候,任何记录行都可以插入成功。前提是待插入的数据行中的id的值符合主键id的唯一性和phone的值符合phone唯一索引的唯一性。
  • 当age=20的时候,并不是说,id的值可以使用任意表中不存在的主键值作为待插入的主键值。此时id的值必须为小于0的数,不能大于0。举例说明:当待插入的数据中的age=20, id=1,那么在非唯一索引age上面存这一行索引记录的时候,会在上图中的蓝色方框20后面在创建一个age=20的记录,还需要为这个非唯一索引下面村上主键索引(聚簇索引)的值:1,此时的1比表中已经存在的主键值0大,所以它会放在0的后面,如上图中所示此时的1会占用被锁住的索引间隙。所以此时不能插入成功。能插入成功的为:age=20, id=-1或age=20, id=-2这样的组合。
  • 当age=27的时候,同理,id的值需要大于15才可以插入成功。比如:age=27, id=16或者age=27, id=17这样的组合。如果此时插入一个age=27, id=14的数据行,你设想一下会怎么存放这个索引记录,索引中已经存在一个age=27, id=15的记录了,此时再来一个age=27, id=14的记录,那这个id=14的记录必须排在id=15的前面。而此时id=14的位置是被间隙锁锁住的。所以它是插入失败的。
  • 上面凡是红色的背景或红色箭头的区域都是有锁的区域,也就是这样的数据不能被插入成功。

实验前的预测:
在这里插入图片描述

实验截图:
在这里插入图片描述

实验使用到的SQL语句:

insert into userinfo (id, name, age, phone, remark) values(1, 'name1', 20, 'phone1', 'id=1导致被阻塞,改为id<1的值就可以成功');
insert into userinfo (id, name, age, phone, remark) values(-1, 'name-1', 21, 'phone-1', 'age=21导致被阻塞,改为age<21或age>27就可以成功');
insert into userinfo (id, name, age, phone, remark) values(1, 'name1', 21, 'phone1', 'age=21导致被阻塞,只要20<age<27,不管其他列是什么值,都会被阻塞');
insert into userinfo (id, name, age, phone, remark) values(-1, 'name-1', 20, 'phone-1', '可以插入成功');
insert into userinfo (id, name, age, phone, remark) values(14, 'name14', 27, 'phone14', 'id=14导致被阻塞,改为id>15就可以插入成功');
insert into userinfo (id, name, age, phone, remark) values(16, 'name16', 26, 'phone16', 'age=26导致被阻塞,改为age<20或age>26就可以成功');
insert into userinfo (id, name, age, phone, remark) values(14, 'name14', 26, 'phone14', 'age=26导致被阻塞,只要20<age<27,不管其他列是什么值,都会被阻塞');
insert into userinfo (id, name, age, phone, remark) values(16, 'name16', 27, 'phone16', '可以插入成功');

RR级别+普通字段列

如果是使用如下的一个普通字段来加锁,会是什么情况呢?

select * from userinfo where name = 'liuqiangdong' for update;

此时加锁的情况是这样的:因为name是一个普通的列,上面没有任何索引可以使用,所以根据这个条件进行搜索数据的时候,会进行全表扫描的操作,当搜索到第一个name='liuqiangdong’的数据行的时候,不会马上停下来,因为后面可能还有很多个name='liuqiangdong’的数据行,所以要进行全表扫描。根据前面我们说的加锁规则,凡是扫描到的对象都要加锁,所以此时全表中的每一个主键索引记录上都有一个X锁。同时为了防止幻读的凡是,会对这个表上所有的主键索引的间隙也都增加上间隙锁。

加锁情况示意图如下:
在这里插入图片描述

实验过程:
在这里插入图片描述

总结

在可重复读RR隔离级别下,间隙锁的加锁规则如下,如果不是RR级别,也就不会有间隙锁存在了,所以间隙锁只在RR级别下才会存在。

  • 原则 1:加锁的基本单位是临键锁next-key lock。next-key lock是前开后闭区间。
  • 原则 2:查找过程中访问到的对象才会加锁。
  • 优化 1:索引上的等值查询,给唯一索引加锁的时候,next-key lock 退化为行锁。
  • 优化 2:索引上的等值查询,向右遍历时且最后一个值不满足等值条件的时候,next-key lock 退化为间隙锁。
  • 一个 bug:唯一索引上的范围查询会访问到不满足条件的第一个值为止,这个在MySQL8.0以后已经修复,但是在MySQL5.7版本中有这个问题。

微信搜索“coder-home”或扫一扫下面的二维码,关注公众号,第一时间了解更多干货分享,还有各类视频教程资源。扫描它,带走我


间隙锁的加锁和解锁过程 间隙锁的加锁和解锁过程是 MySQL 事务处理和并发控制机制的重要组成部分。在事务执行查询操作时,数据库会根据查询条件获取间隙锁,以防止其他事务在锁定的间隙范围内进行插入、删除或更新操作。当事务完成时,无论是提交还是回滚,都会触发间隙锁的解锁操作,释放锁并唤醒被阻塞的事务。了解间隙锁的加锁和解锁过程,可以帮助我们更好地理解 MySQL 的事务隔离级别和并发控制机制,从而在实际应用中进行更有效的数据库设计和性能优化。 阅读详情

相关推荐

间隙锁的实现原理

间隙锁的实现原理是基于 MySQL 的 B+树索引和数据存储结构,通过锁定查询范围的间隙来防止幻读现象的发生。间隙锁的实现方式包括锁的类型与存储、锁的获取与冲突检测以及锁的释放与清理等过程。了解间隙锁的实现原理,可以帮助我们更好地理解 MySQL 的事务隔离级别和并发控制机制,从而在实际应用中进行更有效的数据库设计和性能优化。

yonggeit的博客 3209

心灵拷问:MySQL 到底是怎么加行级锁、间隙锁、临键锁的?

Next-Key Lock 是一张间隙锁,相较于行锁只锁定一行,它会锁定一个区间范围,加锁的范围区间内的索引键值会被锁定 MySQL InnoDB支持三种行锁定方式 InnoDB的默认加锁方式是next-key。如某个加锁操作未使用到索引,则该锁会退化为表锁。 行锁 (Record Lock):存在唯一索引中 (包含主键索引),锁定单条索引记录,即key。 间隙锁 (Gap Lock):存在非唯一索引中,锁定索引记录间隙,确保索引记录的间隙不变。 临键锁 (Next-Key Lo.

祝我飞黄腾达 6654

阻抗匹配与史密斯(Smith)圆图

在找到点B和B'后,我们就能够测量A'到B和B'到D的弧长,前者就是C的归一化电纳值,后者为L的归一化电抗值。当然,表面上看新的点好像是一个不同的阻抗,实际上Z和1/Y表示的是同一个元件(这个新值在圆图上呈现为一个不同的点,而且反射系数也不相同,依次类推)。出现这种情况的原因是我们的图形本身是一个阻抗图,而新的点代表的是一个导纳。这个方程是在复平面(Γr, Γi)上、圆的参数方程(x - a)² + (y - b)² = R²,它以[r/(r + 1), 0]为圆心,半径为1/(1 + r)。

qq_55759599的博客 3962

MySQL-间隙锁-加锁规则

MySQL 后面的版本可能会改变加锁策略,本文只适用版本: 5.x 系列 <=5.7.24 8.0 系列 <=8.0.13 间隙锁在可重复读隔离级别下才有效,以下规则只描述了间隙锁: 原则 1:加锁的基本单位是 next-key lock,next-key lock 是前开后闭区间 原则 2:查找过程中访问到的对象才会加锁。这和锁的普适概念,竞争的资源才会加锁同理 优化 1:索引上的等值查询,给唯一索引加锁的时候,next-key lock 退化为行锁 优化 2:索引上的等值查

泰山与水 1801

MT4-EA自动化交易研究笔记(2022-04-22)

自从接触到mt4的EA自动化交易,更让我这个10多年的老程序员看到了曙光,目前来看也确实出了一点成果,只是是否能稳定盈利有待时间的考验,所以开此专栏,一来做做记录与分析,更好的优化我的EA,二来也希望能与更多的高手交流,以完善我的交易系统

t35254056的博客 2291

运算放大器噪声分析实战:从理论到TINA-TI仿真的完整指南

本文深入探讨运算放大器噪声分析的完整流程,从基础理论到TINA-TI仿真实践。详细解析噪声来源、运放噪声模型建立、手工计算方法,并结合TI工具进行高效仿真验证,提供低噪声电路设计优化策略,帮助工程师提升精密电子系统性能。

Jerry的专栏 947

【mysql】锁机制 - 2.行锁间隙锁临键锁

目录1. 锁的几种类型1.1 记录锁(行锁)?Record Lock1.2?间隙锁 Gap Lock1.3 临键锁?Next-Key Lock2. 加锁过程2.1 唯一索引的查询(1) 等值查询, 查询记录存在(2)?等值查询, 查询记录不存在(3) 范围查询2.2 普通索引的查询(1) 等值查询, 查询记录存在(2) 等值查询, 查询记录不存在(3) 范围查询2.3 其他查询2.4 总结对 InnoDB 按照锁粒度可以分为:行锁、间隙锁、临键锁、意向锁即锁住一条记录。 一般在使用主键或者唯一索引进行查找时

2509_94000862的博客 702

VS2019 从零构建 OSG+OSGEarth+OSGQt 开发环境实战指南

本文提供了一份详细的实战指南,指导开发者如何在Windows系统下使用VS2019从零开始编译和配置OSG、OSGEarth与OSGQt开发环境。文章涵盖了从环境准备、源码获取、CMake配置、Visual Studio编译到最终测试的完整流程,并分享了关键的避坑技巧,旨在帮助三维GIS与可视化开发者高效搭建稳定、可控的专业开发平台。

weixin_28826961的博客 367

【MySQL】聊聊唯一索引是如何加锁的

【MySQL】聊聊唯一索引是如何加锁的

芝兰生于深谷,不以无人而不芳 2461

手把手教你用MSPM0G3507和TB6612驱动MG513X电机(附完整代码与PID调速)

本文详细介绍了如何使用MSPM0G3507微控制器和TB6612驱动模块控制MG513X电机,包括硬件连接、软件配置、编码器测速和PID调速等关键步骤。通过完整的代码示例和PID算法实现,帮助开发者快速掌握电机驱动技术,适用于智能小车、机械臂等嵌入式项目。

weixin_30254435的博客 341

人员行为规范检测:YOLOv8+C#实现工厂车间安全监控,违规即报警零延迟

该方案通过YOLOv8的装备检测与姿态估计的动作识别,结合C#的实时管控能力,实现了从“被动巡检”到“主动预警”的转变。相比传统人工,违规响应速度提升10倍,全年可减少90%以上的安全隐患。方案已在3家制造企业落地,支持自定义违规规则(如新增“吸烟”“未系安全带”),可根据车间场景灵活扩展。需要完整的模型训练配置文件(含数据集增强脚本)或C#系统源码(视频处理+报警模块)的,评论区扣“SafetyDetect”,可直接获取部署版本~

这里只有干货:从 Modbus 通信到 MES 对接,从 YOLO 训练到工控机部署,带你搞定工业软件开发全流程。 1175

MySQL InnoDB加锁机制全解析:从行锁、间隙锁到死锁排查

数据库并发访问时,脏读、不可重复读、幻读等问题是事务隔离的经典难题。MySQL InnoDB通过记录锁、间隙锁与临键锁的组合,在可重复读隔离级别下实现了对当前读的严格加锁控制,既保证了数据一致性,也带来了锁等待与死锁风险。理解共享锁与排他锁的兼容关系、索引对加锁范围的影响,以及RC与RR隔离级别的差异,是排查线上Lock wait timeout和死锁故障的关键。本文从一条UPDATE语句的加锁规则入手,结合全表扫描锁表、间隙锁死锁等高频场景,给出实用的优化与排障路径。

weixin_34221654的博客 144

Android Camera驱动开发工程师面试指南:技术深度与实战准备

摘要:上海移远通信招聘Android Camera驱动开发工程师,主要负责Camera传感器驱动开发维护、高通/展锐平台底层开发及技术预研。岗位要求1年以上嵌入式开发经验,精通Camera传感器驱动调试,熟悉高通平台Camera架构及Android HAL框架。具备HAL开发、算法集成或车载/支付行业经验者优先。工作内容以Driver/HAL开发为主,需具备硬件接口评估能力。该职位接受Linux/单片机背景人员转型。

郑伟强dev的专栏 281

17 面试官:MySQL 间隙锁到底是什么?三张图说清楚它什么时候加、怎么加

本文深入剖析了 MySQL InnoDB 引擎中用于防止幻读的关键机制——间隙锁(Gap Lock)与临键锁(Next-Key Lock)。文章从锁的类型划分讲起,澄清了记录锁、间隙锁和临键锁的区别与联系。重点通过源码层面解读了临键锁的加锁规则,并结合唯一索引等值查询、普通索引等值查询和范围查询三大经典场景,详细拆解了不同条件下的加锁范围。最后总结了“无索引导致全表锁”、“插入意向锁与间隙锁冲突”和“RC级别无间隙锁”三个生产环境中最易踩中的坑,并提供了面试官视角的标准回答模板,帮助读者彻底掌握这一高频面试

weixin_42023666的博客 737

100:vue+cesium: 加载glb文件,随机位置加载2000架飞机

本示例在 Vue + cesium 项目中随机位置加载2000架飞机,飞机是glb文件,每个大小为571kb。这个示例属于性能优化的范畴内,通常如果用entity加载glb只能显示几个飞机,这里采用primitive的方法来加载。直接复制下面的 vue+cesium源代码,操作2分钟即可运行实现效果.

大剑师兰特的GIS世界 706

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

揭秘MySQL:深度解析一条SQL的加锁机制

在本节中,我们将通过一个具体的实例来分析一条SQL的加锁过程。我们将使用一个简单的订单系统来模拟并发访问数据库的场景。通过实例的分析,我们可以总结出一些实践经验和优化建议,帮助我们更好地应对并发访问数据库的挑战。

博客 344

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

MySQL 间隙锁

一.根据案例二:不同索引加锁顺序的问题,模拟重现死锁(详细操作步骤) 1.RR级别下,更新操作默认会加行级锁,行级锁会对索引加锁 2.如果更新语句使用多个索引,行级锁会先锁定普通索引,再锁定聚簇索引 3.如果两个SQL用到了不同的普通索引,或者一个用了,另外一个没用 4.会导致这两个SQL加行级锁的顺序不一致,形成多个事物之间X锁的循环等待,形成死锁 1.1表结构 root@slav...

a82831154的博客 197

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

mysql的加锁机制_从一个案例 复习MySQL加锁机制

一前言该文源自于和一个DBA 同行 @邱神医 (集数据库技术和医学知识于一身的DBA)的技术讨论。RC级别:createtablet1(idintprimarykey,namevarchar(30));insertintot1values(1,'a'),(4,'c'),(7,'b'),(10,'a'),(20,'d'),(30,'b');commit;案例一--se...

weixin_35197188的博客 142

MySQL锁、加锁机制(超详细)—— 锁分类、全局锁、共享锁、排他锁;表锁、元数据锁、意向锁;行锁、间隙锁、临键锁;乐观锁

客户端发往MySQL的一条条SQL语句,实际上都可以理解成一个个单独的事务(一条sql语句默认就是一个事务)。而事务是基于数据库连接的,每个数据库连接在MySQL中,又会用一条工作线程来维护,也意味着一个事务的执行,本质上就是一条工作线程在执行,当出现多个事务同时执行时,这种情况则被称之为并发事务,所谓的并发事务也就是指多条线程并发执行。多线程并发执行自然就会出问题,也就是MySQL基础:事务、并发事务四大问题、事务隔离级别——脏写、脏读、不可重复读、幻读中提到的脏写、脏读、不可重复读及幻读问题。

m0_46995061的博客 154

一文讲不清mysql里的加锁机制

首先你要知道:仅仅一篇文章是无法全面讲清楚明白mysql里面的加锁机制的! 虽然网上有很多文章都号称“理解mysql里的加锁机制看这一篇就够了”,实际上都只是理论方面到位,工程实践方面则都所不足。 本文针对工程实践方面经常会碰到的一些关于锁的问题进行剖析: 1.锁的类型: 经常碰到的主...

269

MySQL:用动态的观点看加锁

首先复习一下加锁规则:原则1:加锁的基本单位是next-key lock,是一个前开后闭区间;原则2:查找过程中访问到的对象才会加锁;优化1:索引上的等值查询,给唯一索引加锁的时候,next-key lock退化为行锁;优化2:索引上的等值查询,向右遍历时且最后一个值不满足等值条件的时候,next-key lock退化为间隙锁;一个bug:唯一索引上的范围查询会访问到不满足条件的第一个值为止。

dsgdauigfs的博客 1173
上一篇: MySQL在RR级别下到底有没有修复幻读
下一篇: MySQL如何按周统计表中数据
程序猿集锦
博客等级 码龄18年 55粉丝 46原创
评论 5
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值