返回顶部
首页 > 资讯 > 数据库 >MySQL数据库InnoDB引擎行级锁锁定范围是什么
  • 753
分享到

MySQL数据库InnoDB引擎行级锁锁定范围是什么

2024-04-02 19:04:59 753人浏览 独家记忆
摘要

这篇文章主要介绍Mysql数据库InnoDB引擎行级锁锁定范围是什么,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!         

这篇文章主要介绍Mysql数据库InnoDB引擎行级锁定范围是什么,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!

                                                       mysql数据库InnoDB引擎支持行级锁,也就是说我们可以对表中某些行数据执行锁定操作,锁定操作的影响是:如果一个事物对表中某行执行了锁定操作,而另一个事务也需要对同样的行执行锁定操作,这样第二个事务的锁定操作有可能被阻塞,一旦被阻塞第二个事务只能等到第一个事务执行完毕(提交或回滚)或超时。

背景知识

上面我们简单的介绍了InnoDB的行级锁,为了理解后面的验证部分,需要补充一下背景知识。如果对相应知识非常了解,可以直接跳转到验证部分内容。

1. InnoDB锁的类型

InnoDB引擎使用了七种类型的锁,他们分别是:

  • 共享排他锁(Shared and Exclusive Locks)

  • 意向锁(Intention Locks)

  • 记录锁(Record Locks)

  • 间隙锁(Gap Locks)

  • Next-Key Locks

  • 插入意图锁(Insert Intention Locks)

  • 自增锁(AUTO-INC Locks)

本文主要涉及Shared and Exclusive Locks,Record Locks,Gap Locks,Next-Key Locks这几种锁,其他类型锁如果大家感兴趣可以自己深入了解,在此不在详述。

1.1 Shared and Exclusive Locks

共享锁(S锁)和排他锁(X锁)的概念在许多编程语言中都出现过。先来描述一下这两种锁在Mysql中的影响结果:

  • 如果一个事务对某一行数据加了S锁,另一个事务还可以对相应的行加S锁,但是不能对相应的行加X锁。

  • 如果一个事务对某一行数据加了X锁,另一个事务既不能对相应的行加S锁也不能加X锁。

用一张经典的矩阵表格继续说明共享锁和排他锁的互斥关系:

--SX
S01
X11

图中S表示共享锁X表示独占锁,0表示锁兼容1表示锁冲突,兼容不被阻塞,冲突被阻塞。由表可知一旦一个事务加了排他锁,其他个事务加任何锁都需要等待。多个共享锁不会相互阻塞。

1.2 Record Locks、Gap Locks、Next-Key Locks

这三种类型的锁都描述了锁定的范围,故放在一起说明。

以下定义摘自MySQL官方文档

  • 记录锁(Record Locks):记录锁锁定索引中一条记录。

  • 间隙锁(Gap Locks):间隙锁要么锁住索引记录中间的值,要么锁住第一个索引记录前面的值或者最后一个索引记录后面的值。

  • Next-Key Locks:Next-Key锁是索引记录上的记录锁和在索引记录之前的间隙锁的组合。

定义中都提到了索引记录(index record)。为什么?行锁和索引有什么关系呢?其实,InnoDB是通过搜索或者扫描表中索引来完成加锁操作,InnoDB会为他遇到的每一个索引数据加上共享锁或排他锁。所以我们可以称行级锁(row-level locks)为索引记录锁(index-record locks),因为行级锁是添加到行对应的索引上的。

三种类型锁的锁定范围不同,且逐渐扩大。我们来举一个例子来简要说明各种锁的锁定范围,假设表t中索引列有3、5、8、9四个数字值,根据官方文档的确定三种锁的锁定范围如下:

  • 记录锁的锁定范围是单独的索引记录,就是3、5、8、9这四行数据。

  • 间隙锁的锁定为行中间隙,用集合表示为(-∞,3)、(3,5)、(5,8)、(8,9)、(9,+∞)。

  • Next-Key锁是有索引记录锁加上索引记录锁之前的间隙锁组合而成,用集合的方式表示为(-∞,3]、(3,5]、(5,8]、(8,9]、(9,+∞)。

最后对于间隙锁还需要补充三点:

  1. 间隙锁阻止其他事务对间隙数据的并发插入,这样可有有效的解决幻读问题(Phantom Problem)。正因为如此,并不是所有事务隔离级别都使用间隙锁,MySQL InnoDB引擎只有在Repeatable Read(默认)隔离级别才使用间隙锁。

  2. 间隙锁的作用只是用来阻止其他事务在间隙中插入数据,他不会阻止其他事务拥有同样的的间隙锁。这就意味着,除了insert语句,允许其他SQL语句可以对同样的行加间隙锁而不会被阻塞

  3. 对于唯一索引的加锁行为,间隙锁就会失效,此时只有记录锁起作用

2. 加锁语句

前面我们已经介绍了InnoDB的是在SQL语句的执行过程中通过扫描索引记录的方式来实现加锁行为的。那哪些些语句会加锁?加什么样的锁?接下来我们逐一描述:

  • select ... from语句:InnoDB引擎采用多版本并发控制(mvcC)的方式实现了非阻塞读,所以对于普通的select读语句,InnoDB并不会加锁【注1】。

  • select ... from lock in share mode语句:这条语句和普通select语句的区别就是后面加了lock in share mode,通过字面意思我们可以猜到这是一条加锁的读语句,并且锁类型为共享锁(读锁)。InnoDB会对搜索的所有索引记录加next-key锁,但是如果扫描的唯一索引的唯一行,next-key降级为索引记录锁。

  • select ... from for update语句:和上面的语句一样,这条语句加的是排他锁(写锁)。InnoDB会对搜索的所有索引记录加next-key锁,但是如果扫描唯一索引的唯一行,next-key降级为索引记录锁。

  • update ... where ...语句:。InnoDB会对搜索的所有索引记录加next-key锁,但是如果扫描唯一索引的唯一行,next-key降级为索引记录锁。【注2】

  • delete ... where ...语句:。InnoDB会对搜索的所有索引记录加next-key锁,但是如果扫描唯一索引的唯一行,next-key降级为索引记录锁。

  • insert语句:InnoDB只会在将要插入的那一行上设置一个排他的索引记录锁。

最后补充两点:

  1. 如果一个查询使用了辅助索引并且在索引记录加上了排他锁,InnoDB会在相对应的聚合索引记录上加锁。

  2. 如果你的SQL语句无法使用索引,这样MySQL必须扫描整个表以处理该语句,导致的结果就是表的每一行都会被锁定,并且阻止其他用户对该表的所有插入。

SQL语句验证

闲言少叙,接下来我们进入本文重点SQL语句验证部分。

1.测试环境

数据库:MySQL 5.6.35  
事务隔离级别:Repeatable read  
数据库访问终端:mysql client

2.验证场景

2.1 场景一

建表:

CREATE TABLE `user` (
 `id` int(11) NOT NULL,
 `name` varchar(8) NOT NULL,
 PRIMARY KEY (`id`),
 KEY `name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

插入数据:

INSERT INTO `user` (`id`, `name`) VALUES ('1', 'a');
INSERT INTO `user` (`id`, `name`) VALUES ('3', 'c');
INSERT INTO `user` (`id`, `name`) VALUES ('5', 'e');
INSERT INTO `user` (`id`, `name`) VALUES ('7', 'g');
INSERT INTO `user` (`id`, `name`) VALUES ('9', 'i');

首先我们执行SQL语句的模板:

步骤client 1client 2
1begin;--
2SELECT * FROM user where name='e' for update;--
3--begin;
4--INSERT INTO `user` (`id`, `name`) VALUES (10, #{name});
5rollback;--
6--rollback;

替换步骤5中name的值,观察结果:

name的值执行结果
a不阻塞
b不阻塞
d阻塞
e阻塞
f阻塞
h不阻塞
i不阻塞

观察结果,我们发现SQL语句
SELECT * FROM user where name='e' for update
一共锁住索引name中三行记录,(c,e]区间应该是next-key锁而(e,h)区间是索引记录e后面的间隙。

接下来我们确定next-key锁中哪部分是索引记录锁哪部分是间隙锁。

执行SQL语句的模板:

步骤client 1client 2
1begin;--
2SELECT * FROM user where name='e' for update;--
3--SELECT * FROM user where name=#{name} for update;
5rollback;--
6--rollback;

替换步骤5中name的值,观察结果:

name的值执行结果
d不阻塞
e阻塞
f不阻塞

因为间隙锁只会阻止insert语句,所以同样的索引数据,insert语句阻塞而select for update语句不阻塞的就是间隙锁,如果两条语句都阻塞就是索引记录锁。

观察执行结果可知,d和f为间隙锁,e为索引记录锁。

结论:通过两条SQL,我们确定了对于辅助索引name在查询条件为 where name='e'  时的加锁范围为(c,e],(e,g),其中:

  • 对SQL语句扫描的索引记录e加索引记录锁[e]。

  • 锁定了e前面的间隙,c到e之间的数据(c,e)加了间隙锁

  • 前两个构成了next-key锁(c,e]。

  • 值得注意的是还锁定了e后面的间隙(e,g)。

说的这里细心的读者可能已经发现我们的测试数据中没有间隙的边界数据c和g。接下来我们就对间隙边界值进行测试。

执行SQL语句的模板:

步骤client 1client 2
1begin;--
2SELECT * FROM user where name='e' for update;--
3--begin;
4--INSERT INTO `user` (`id`, `name`) VALUES (#{id}, #{name});
5rollback;--
6--rollback;

替换步骤5中id,name的值,观察结果:

id的值name=c执行结果id的值name=g执行结果
-------3g组塞
-------2g阻塞
-1c不阻塞-1g阻塞
1c不阻塞1g不阻塞
2c不阻塞2g阻塞
3c不阻塞3g不阻塞
4c阻塞4g阻塞
5c阻塞5g阻塞
6c阻塞6g阻塞
7c不阻塞7g不阻塞
8c阻塞8g不阻塞
9c不阻塞9g不阻塞
10c阻塞10g不阻塞
11c阻塞---
12c阻塞---

通过观察以上执行结果,我们发现,name等于c和e时insert语句的结果随着id值得不同一会儿锁定,一会儿不锁定。那一定是id列加了锁才会造成这样的结果。

如果先不看id=5这一行数据的结果,我们发现一个规律:

  • name=c时,name=c对应的id=3的id聚合索引数据记录之后的间隙(3,5),(5,7),(7,9),(9,∞)都被加上了锁。

  • name=e时,name=e对应的id=7的id聚合索引数据记录之前的间隙(5,7),(3,5),(1,3),(-∞,1)都被加上了锁。

  • 我们可用select * from user where id = x for update;语句判断出以上间隙上加的锁都为间隙锁。

接下来我们解释一下id=5的锁定情况

执行SQL语句的模板:

步骤client 1client 2
1begin;--
2SELECT * FROM user where name='e' for update;--
3--SELECT * FROM user where id=#{id} for update;
5rollback;--
6--rollback;

替换步骤5中id的值,观察结果:

id的值执行结果
3不阻塞
4不阻塞
5阻塞
6不阻塞
7 不阻塞

通过观察执行结果可知,id=5的聚合索引记录上添加了索引记录锁。根据MySQL官方文档描述,InnoDB引擎在对辅助索引加锁的时候,也会对辅助索引所在行所对应的聚合索引(主键)加锁。而主键是唯一索引,在对唯一索引加锁时,间隙锁失效,只使用索引记录锁。所以SELECT * FROM user where name='e' for update;不仅对辅助索引name=e列加上了next-key锁,还对对应的聚合索引id=5列加上了索引记录锁。

最终结论:  
对于SELECT * FROM user where name='e' for update;一共有三种锁定行为:

  1. 对SQL语句扫描过的辅助索引记录行加上next-key锁(注意也锁住记录行之后的间隙)。

  2. 对辅助索引对应的聚合索引加上索引记录锁。

  3. 当辅助索引为间隙锁“最小”和“最大”值时,对聚合索引相应的行加间隙锁。“最小”锁定对应聚合索引之后的行间隙。“最大”值锁定对应聚合索引之前的行间隙。

上面我们将对辅助索引加锁的情况介绍完了,接下来我们测试一下对聚合索引和唯一索引加锁。

2.2 场景二

建表:

CREATE TABLE `user` (
  `id` int(11) NOT NULL,
  `name` varchar(8) NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `index_name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

注意与场景一表user不同的是name列为唯一索引。

插入数据:

INSERT INTO `user` (`id`, `name`) VALUES ('1', 'a');
INSERT INTO `user` (`id`, `name`) VALUES ('3', 'c');
INSERT INTO `user` (`id`, `name`) VALUES ('5', 'e');
INSERT INTO `user` (`id`, `name`) VALUES ('7', 'g');
INSERT INTO `user` (`id`, `name`) VALUES ('9', 'i');

首先我们执行SQL语句的模板:

步骤client 1client 2
1begin;--
2SELECT * FROM user where name='e' for update;
3--begin;
4--INSERT INTO `user` (`id`, `name`) VALUES (10, #{name});
5rollback;--
6--rollback;

替换步骤5中name的值,观察结果:

name的值执行结果
a不阻塞
b不阻塞
c不阻塞
d不阻塞
e阻塞
f不阻塞
g不阻塞
h不阻塞
i不阻塞

由测试结果可知,只有name='e'这行数据被锁定。

通过SQL语句我们验证了,对于唯一索引列加锁,间隙锁失效,

2.3 场景三

场景一和场景二都是在查询条件等于的情况下做出的范围判断,现在我们尝试一下其他查询条件,看看结论是否一致。

借用场景一的表和数据。

建表:

CREATE TABLE `user` (
  `id` int(11) NOT NULL,
  `name` varchar(8) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `index_name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

插入数据:

INSERT INTO `user` (`id`, `name`) VALUES ('1', 'a');
INSERT INTO `user` (`id`, `name`) VALUES ('3', 'c');
INSERT INTO `user` (`id`, `name`) VALUES ('5', 'e');
INSERT INTO `user` (`id`, `name`) VALUES ('7', 'g');
INSERT INTO `user` (`id`, `name`) VALUES ('9', 'i');

执行SQL语句的模板:

步骤client 1client 2
1begin;--
2SELECT * FROM user where name>'e' for update;--
3--begin;
4--INSERT INTO `user` (`id`, `name`) VALUES ('10', #{name});
5rollback;--
6--rollback;

替换步骤5中name的值,观察结果:

name的值执行结果
a阻塞
b阻塞
c阻塞
d阻塞
e阻塞
f阻塞
g阻塞
h阻塞
i阻塞

这个结果是不是和你想象的不太一样,这个结果表明where name>'e'这个查询条件并不是锁住'e'列之后的数据,而锁住了所有name列中所有数据和间隙。这是为什么呢?

我们执行以下的SQL语句执行计划:

 explain select * from user where name>'e' for update;

执行结果:

+----+-------------+-------+-------+---------------+------------+---------+------+------+--------------------------+
| id | select_type | table | type  | possible_keys | key        | key_len | ref  | rows | Extra                    |
+----+-------------+-------+-------+---------------+------------+---------+------+------+--------------------------+
|  1 | SIMPLE      | user  | index | index_name    | index_name | 26      | NULL |    5 | Using where; Using index |
+----+-------------+-------+-------+---------------+------------+---------+------+------+--------------------------+
1 row in set (0.00 sec)

如果你的结果与上面不同先执行一下OPTIMIZE TABLE user;再执行以上语句。

通过观察SQL语句的执行计划我们发现,语句使用了name列索引,且rows参数等于5,user表中一共也只有5行数据。SQL语句的执行过程中一共扫描了name索引记录5行数据且对这5行数据都加上了next-key锁,符合我们上面的执行结果。

接下来我们再制造一组数据。  
建表:

CREATE TABLE `user` (
 `id` int(11) NOT NULL,
 `name` varchar(8) NOT NULL,
 `age` int(11) NOT NULL,
 PRIMARY KEY (`id`),
 KEY `index_name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

插入数据:

INSERT INTO `user` (`id`, `name`,`age`) VALUES ('1', 'a','15');
INSERT INTO `user` (`id`, `name`,`age`) VALUES ('3', 'c','20');
INSERT INTO `user` (`id`, `name`,`age`) VALUES ('5', 'e','16');
INSERT INTO `user` (`id`, `name`,`age`) VALUES ('7', 'g','19');
INSERT INTO `user` (`id`, `name`,`age`) VALUES ('9', 'i','34');

这张表和前表的区别是多了一列非索引列age

我们再执行一下同样的SQL语句执行计划:

 explain select * from user where name>'e' for update;

执行结果:

+----+-------------+-------+-------+---------------+------------+---------+------+------+-----------------------+
| id | select_type | table | type  | possible_keys | key        | key_len | ref  | rows | Extra                 |
+----+-------------+-------+-------+---------------+------------+---------+------+------+-----------------------+
|  1 | SIMPLE      | user  | range | index_name    | index_name | 26      | NULL |    2 | Using index condition |
+----+-------------+-------+-------+---------------+------------+---------+------+------+-----------------------+
1 row in set (0.00 sec)

是不是和第一次执行结果不同了,rows参数等于2,说明扫描了两行记录,结合SQL语句select * from user where name>'e' for update;执行后返回结果我们判断这两行记录应该为g和i。

因为select * from user where name>'e' for update;语句扫描了两行索引记录分别是g和i,所以我们将g和i的锁定范围叠就可以得到where name>'e'的锁定范围:

  1. 索引记录g在name列锁定范围为(e,g],(g,i)。索引记录i的在name列锁定范围为(g,i],(i,+∞)。两者叠加后锁定范围为(e,g],(g,i],(i,+∞)。其中g,i为索引记录锁。

  2. g和i对应id列中的7和9加索引记录锁。

  3. name列的值为锁定范围上边界e时,还会在e所对应的id列值为5之后的所有值之间加上间隙锁,范围为(5,7),(7,9),(9,+∞)。下边界为+∞无需考虑。

接下来我们逐一测试:

首先测试验证了next-key锁范围,执行SQL语句的模板:

步骤client 1client 2
1begin;--
2SELECT * FROM user where name>'e' for update;--
3--begin;
4--INSERT INTO `user` (`id`, `name`, `age`) VALUES ('10', #{name},'18');
5rollback;--
6--rollback;

替换步骤5中name的值,观察结果:

name的值执行结果
a不阻塞
b不阻塞
c不阻塞
d不阻塞
f阻塞
g阻塞
h阻塞
i阻塞
j阻塞
k阻塞

下面验证next-key锁中哪部分是间隙锁,哪部分是索引记录锁,执行SQL语句的模板:

步骤client 1client 2
1begin;--
2SELECT * FROM user where name>'e' for update;--
3--SELECT * FROM user where name=#{name} for update;
5rollback;--
6--rollback;

替换步骤5中name的值,观察结果:

name的值执行结果
e不阻塞
f不阻塞
g阻塞
h不阻塞
i阻塞
j不阻塞

接下来验证对id列加索引记录锁,执行SQL语句的模板:

步骤client 1client 2
1begin;--
2SELECT * FROM user where name>'e' for update;--
3--SELECT * FROM user where id=#{id} for update;
5rollback;--
6--rollback;

替换步骤5中id的值,观察结果:

id的值执行结果
5不阻塞
6 不阻塞
7阻塞
8不阻塞
9阻塞
10不阻塞

最后我们验证name列的值为边界数据e时,id列间隙锁的范围,执行SQL语句的模板:

步骤client 1client 2
1begin;--
2SELECT * FROM user where name>'e' for update;--
3--begin;
4--INSERT INTO `user` (`id`, `name`,`age`) VALUES (#{id}, 'e','18');
5rollback;--
6--rollback;

替换步骤5中id的值,观察结果:

id的值执行结果
-1不阻塞
1不阻塞
2不阻塞
3不阻塞
4不阻塞
5不阻塞
6阻塞
7阻塞
8阻塞
9阻塞
10阻塞
11阻塞
12阻塞

注意7和9是索引记录锁记录锁

观察上面的所有SQL语句执行结果,可以验证select * from user where name>'e' for update的锁定范围为此语句扫描name列索引记录g和i的锁定范围的叠加组合。

2.4 场景四

我们通过场景三验证了普通索引的范围查询语句加锁范围,现在我们来验证一下唯一索引的范围查询情况下的加锁范围。有了场景三的铺垫我们直接跳过扫描全部索引的情况,创建可以扫描范围记录的表结构并插入相应数据测试。

建表:

CREATE TABLE `user` (
  `id` int(11) NOT NULL,
  `name` varchar(8) NOT NULL,
  `age` int(11) NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `index_name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

插入数据:

INSERT INTO `user` (`id`, `name`,`age`) VALUES ('1', 'a','15');
INSERT INTO `user` (`id`, `name`,`age`) VALUES ('3', 'c','20');
INSERT INTO `user` (`id`, `name`,`age`) VALUES ('5', 'e','16');
INSERT INTO `user` (`id`, `name`,`age`) VALUES ('7', 'g','19');
INSERT INTO `user` (`id`, `name`,`age`) VALUES ('9', 'i','34');

和场景三表唯一不同是name列为唯一索引。

SQL语句select * from user where name>'e'扫描name列两条索引记录g和i。如果需要只对g和i这两条记录加上记录锁无法避免幻读的发生,索引锁定范围应该还是两条数据next-key锁锁的组合:(e,g],(g,i],(i,+∞)。其中g,i为索引记录锁

我们通过SQL验证我们的结论,执行SQL语句的模板:

步骤client 1client 2
1begin;--
2SELECT * FROM user where name>'e' for update;--
3--begin;
4--INSERT INTO `user` (`id`, `name`, `age`) VALUES ('10', #{name},'18');
5rollback;--
6--rollback;

替换步骤5中name的值,观察结果:

name的值执行结果
a不阻塞
b不阻塞
c不阻塞
d不阻塞
f阻塞
g阻塞
h阻塞
i阻塞
j阻塞
k阻塞

下面验证next-key锁中哪部分是间隙锁,哪部分是索引记录锁,执行SQL语句的模板:

步骤client 1client 2
1begin;--
2SELECT * FROM user where name>'e' for update;--
3--SELECT * FROM user where name=#{name} for update;
5rollback;--
6--rollback;

替换步骤5中name的值,观察结果:

name的值执行结果
e不阻塞
f不阻塞
g阻塞
h不阻塞
i阻塞
j不阻塞

通过上面两条SQL语句的验证结果,我们证明了我们的g和i的锁定范围趋势为两者next-key叠加组合。

接下来我们验证一下对辅助索引加锁后对聚合索引的锁转移,执行SQL语句的模板:

步骤client 1client 2
1begin;--
2SELECT * FROM user where name>'e' for update;--
3--SELECT * FROM user where id=#{id} for update;
5rollback;--
6--rollback;

替换步骤5中id的值,观察结果:

id的值执行结果
5不阻塞
6 不阻塞
7阻塞
8不阻塞
9阻塞
10不阻塞

由结果可知对辅助索引name中的g和i列对应的聚合索引id列中的7和9加上了索引记录锁。

到目前为止所有实验结果和场景三完全一样,这也很好理解,毕竟场景四和场景三只是辅助索引name的索引类型不同,一个是唯一索引,一个是普通索引。

最后验证意向,next-key锁边界数据e,看看结论时候和场景三相同。

执行SQL语句的模板:

步骤client 1client 2
1begin;--
2SELECT * FROM user where name>'e' for update;--
3--begin;
4--INSERT INTO `user` (`id`, `name`,`age`) VALUES (#{id}, 'e','18');
5rollback;--
6--rollback;

替换步骤5中id的值,观察结果:

id的值执行结果
-1不阻塞
1不阻塞
2不阻塞
3不阻塞
4不阻塞
5不阻塞
6不阻塞
7阻塞
8不阻塞
9阻塞
10不阻塞
11不阻塞
12不阻塞

注意7和9是索引记录锁记录锁

通过结果可知,当name列为索引记录上边界e时,并没有对id有加锁行为,这点与场景三不同。

对于唯一索引的范围查询和普通索引的范围查询类似,唯一不同的是当辅助索引等于上下范围的边界值是不会对主键加上间隙锁。

唯一索引范围查询加锁范围:

  • 对于扫描的辅助索引记录的锁定范围就是多个索引记录next-key范围的叠加组合。

  • 对于聚合索引(主键)的锁定范围,会对多个辅助索引对应的聚合索引列加索引记录锁。

结论

InnoDB引擎会对他扫描过的索引记录加上相应的锁,通过“场景一”我们已经明确了扫描一条普通索引记录的锁定范围,通过“场景三”我们可以推断任意多个扫描普通索引索引记录的锁定范围。通过“场景二”我们确定了扫描一条唯一索引记录(或主键)的锁定范围。通过“场景四”我们可以推断任意多个扫描索唯一引记录(或主键)的锁定范围。在实际的应用可以灵活使用,判断两条SQL语句是否相互锁定。这里还需要注意的是对于索引的查询条件,不能想当然的理解,他往往不是我们理解的样子,需要结合执行计划判断索引最终扫描的记录数,否则会对加锁范围理解产生偏差。




备注

注1:在事务隔离级别为SERIALIZABLE时,普通的select语句也会对语句执行过程中扫描过的索引加上next-key锁。如果语句扫描的是唯一索引,那就将next-key锁降级为索引记录锁了。  
注2:当更新语句修改聚合索引(主键)记录时,会对受影响的辅助索引执行隐性的加锁操作。当插入新的辅助索引记录之前执行重复检查扫描时和当插入新的辅助索引记录时,更新操作还对受影响的辅助索引记录添加共享锁。

以上是“MySQL数据库InnoDB引擎行级锁锁定范围是什么”这篇文章的所有内容,感谢各位的阅读!希望分享的内容对大家有帮助,更多相关知识,欢迎关注编程网数据库频道!

您可能感兴趣的文档:

--结束END--

本文标题: MySQL数据库InnoDB引擎行级锁锁定范围是什么

本文链接: https://lsjlt.com/news/54880.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • MySQL数据库InnoDB引擎行级锁锁定范围是什么
    这篇文章主要介绍MySQL数据库InnoDB引擎行级锁锁定范围是什么,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!         ...
    99+
    2024-04-02
  • MYSQL数据库Innodb 引擎mvcc锁实现原理
    目录1 数据库设置隔离级别2 数据库表以及案例操作3 mvcc 实现原理4 ACID 的实现前言: 大家都知道在java 开发过程中,会经常用到锁,在java 代码中,我们都知道锁是...
    99+
    2024-04-02
  • mysql数据库中行级锁、表级锁和页级锁的区别是什么
    这篇文章主要介绍了mysql数据库中行级锁、表级锁和页级锁的区别是什么,具有一定借鉴价值,需要的朋友可以参考下。下面就和我一起来看看吧。按粒度可以分为:1、行级锁,MySQL中锁定粒度最细的一种锁,表示只针...
    99+
    2024-04-02
  • 浅谈MySql update会锁定哪些范围的数据
    目录1、背景2、前置知识2.1 数据库的隔离级别2.2 数据库版本2.3 数据库的存储引擎2.4 锁是加在记录上还是索引上2.5 update...where加锁的基本单位是2.6 行级锁3、测试数据...
    99+
    2022-06-24
    MySqlupdate锁定范围 MySqlupdate范围
  • MySQL知识点之InnoDB中的行级锁是什么
    今天小编给大家分享一下MySQL知识点之InnoDB中的行级锁是什么的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下...
    99+
    2024-04-02
  • MySQL数据库锁定机制是什么
    本篇文章给大家分享的是有关MySQL数据库锁定机制是什么,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。1. MySQL 锁定机制简介各存储引擎...
    99+
    2024-04-02
  • MySQL的表级锁,行级锁,排它锁和共享锁是什么
    这篇文章主要介绍“MySQL的表级锁,行级锁,排它锁和共享锁是什么”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“MySQL的表级锁,行级锁,排它锁和共享锁是什么”文章能帮助大家解决问题。前言先说下事...
    99+
    2023-07-02
  • MySQL数据库的引擎是什么
    本篇内容介绍了“MySQL数据库的引擎是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!如果你是个赛车手...
    99+
    2024-04-02
  • mysql数据库锁机制是什么
    小编给大家分享一下mysql数据库锁机制是什么,希望大家阅读完这篇文章后大所收获,下面让我们一起去探讨吧!并发控制数据库管理系统中的并发控制的任务是确保在多个事务同时存取数据库中同一数据时不破坏事务的隔离性...
    99+
    2024-04-02
  • MySQ数据库锁定机制是什么
    本篇内容主要讲解“MySQ数据库锁定机制是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“MySQ数据库锁定机制是什么”吧!1. MySQL 锁定机制简介各存...
    99+
    2024-04-02
  • MySQL数据库中怎么修改引擎为INNODB
    MySQL数据库中怎么修改引擎为INNODB,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。  对于MySQL数据库,如果你要使...
    99+
    2024-04-02
  • MySQL数据库的锁机制是什么
    本篇内容介绍了“MySQL数据库的锁机制是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!为什么要加锁?...
    99+
    2024-04-02
  • 什么是MySQL元数据锁
    这篇文章主要介绍“什么是MySQL元数据锁”,在日常操作中,相信很多人在什么是MySQL元数据锁问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”什么是MySQL元数据锁”的疑惑...
    99+
    2024-04-02
  • MySQL数据库中怎么实现全局锁和表级锁
    这篇文章给大家介绍MySQL数据库中怎么实现全局锁和表级锁,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。1. 全局锁全局锁是粒度比较大的锁,基本上也使用不上,就像我们家的大门一样,控制...
    99+
    2024-04-02
  • MySQL数据库引擎有什么用
    小编给大家分享一下MySQL数据库引擎有什么用,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!  数据库引擎是用于存储、处理和保护...
    99+
    2024-04-02
  • mysql行级锁的实现原理是什么
    MySQL行级锁的实现原理是通过两种方式来实现的:锁的粒度和锁的类型。 锁的粒度: MySQL的行级锁是在InnoDB存储引擎中...
    99+
    2024-04-09
    mysql
  • Mysql数据库中的存储引擎是什么
    这篇文章主要介绍了Mysql数据库中的存储引擎是什么的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Mysql数据库中的存储引擎是什么文章都会有所收获,下面我们一起来看看吧。存储...
    99+
    2023-04-03
    mysql
  • oracle数据库锁表,什么SQL引起了锁表?ORACLE解锁的方法
    --查询数据库锁表记录 select sess.sid, sess.serial#, lo.oracle_username, lo.os_user_name, ao.obj...
    99+
    2019-07-09
    oracle数据库锁表 什么SQL引起了锁表?ORACLE解锁的方法
  • 数据库的锁机制是什么
    数据库的锁机制是一种用于保护数据库的一致性和并发操作的机制。它确保数据库中的数据在被多个并发事务访问和修改时保持一致性,避免数据的混...
    99+
    2023-09-20
    数据库
  • Impala是什么数据库查询引擎
    Impala是一个开源的、高性能的、分布式的SQL查询引擎,用于在Apache Hadoop上进行交互式查询。它允许用户使用标准的S...
    99+
    2024-03-07
    Impala
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作