欢迎光临散文网 会员登陆 & 注册

SpringCloudalibaba+Vue开发仿社交小程序-旧隐辞函谷,新章出汉闱

2023-04-06 01:46 作者:bili_68802470155  | 我要投稿


InnoDB 是如何处理幻读的

前言

SpringCloudalibaba+Vue开发仿社交小程序

download:https://www.51xuebc.com/thread-547-1-1.html

大局部人在日常的业务开发中,其实很少去关注数据库的事务相关问题,根本上都是 CURD 一把梭。正好最近在看 MySQL 的相关根底学问,其中关于幻读问题之前不断没有了解深入,今天就来聊聊「InnoDB 是如何处理幻读的」,话不多说,下面进入主题。

事务隔离级别

事务隔离是数据库处置的根底之一,是 中的 I。在 MySQL 的 InnoDB 引擎中支持在 规范中的四种事务隔离级别,如下图所示,其中 P1 表示脏读(Dirty read),P2 表示不可反复读(Dirty read),P3 表示幻读(Phantom)。

为什么需求定义这么多隔离呢?从上图中也能猜出一二了,InnoDB 提供多个隔离级别主要缘由是:让运用者能够在多个事务同时停止更改和执行查询时微调性能与结果的牢靠性、分歧性和可再现性之间的均衡的设置。是一种性能与结果牢靠性间的 trade off。

什么是幻读

在聊「InnoDB 处理幻读方式」前我们需求先理解幻读是什么

其中我加粗的「result set」是关键的中央,两次查询返回的是结果集,阐明必需是一个范围查询操作。总结下,幻读就是:在同一个事务中,在前后两次查询相同范围时,两次查询得到的结果是不分歧的。所以幻读会产生数据分歧性问题。


InnoDB 处理幻读方式

为理解决上述的幻读问题,InnoDB 引入了两种锁,分别是「间隙锁」和「next-key 锁」。下面经过一个示例来描绘这两种锁的作用分别是什么。假设存在一个这样的 B+ Tree 的索引构造,构造中有 4 个索引元素分别是:9527、9530、9535、9540。

此时当我们运用如下 SQL 经过主键索引查询一条记载,并且加上 X 锁(排它锁)时:

select * from user where id = 9527 for update;

这时就会产生一个记载锁(也就是行锁),锁定 id = 9527 这个索引。

在被锁定的记载(这里是 id = 9527)的锁释放之前,其它事务无法对这条被锁定记载做任何操作。再回想一下,前面说的幻读定义「在同一个事务中,在前后两次查询相同范围时,两次查询得到的结果是不分歧」。留意,这里强调的是范围查询。

InnoDB 要处理幻读问题,就必需得保证在假如在一个事务中,经过如下这条语句停止锁定时:

select * from user where id > 9530 and id < 9535 for update;

此时,另外一个语句再执行一如下这条 insert 语句时,需求被阻塞,直到上面这个取得锁的事务释放锁后才干执行。

insert into user(id, name, age) values(9533, 'Jack', 44);

为此,InnoDB 引入了「间隙锁」,它的主要功用是锁定一段范围内的索引记载。比方上面查询 id > 9530 and id < 9535 的时分,对 B+ Tree 中的(9530,9535)这个开区间范围的索引加间隙锁。

在这种加了间隙锁的状况下,其它事务对这个区间的数据停止插入、更新、删除都会被锁住直到这个获取到锁的事务释放。


这种是在区间之间的状况,你可能想到另外的一种状况:锁定多个区间,如下的一条语句:

select * from user where id > 9530 for update;

上面这条查询语句是针对 id > 9530 这个条件加锁,那么此时它需求锁定多个索引区间,所以在这种状况下 InnoDB 引入了「next-key 锁」机制。其实 next-key 锁的效果相当于间隙锁和记载锁的合集,记载锁锁定存在的记载行,间隙锁锁住记载行之间的间隙,而 next-key 锁它锁住的是两者之和。


在 InnoDB 中,每个数据行上的非独一索引列上都会存在一把 next-key 锁,当某个事务持有该数据行的 next-key 锁时,会锁住一段左开右闭区间的数据。因而,当经过 id > 9530 这样一种范围查询加锁时,会加 next-key 锁,锁定区间是范围是:

(9530,9535] (9535,9540] (9540,+∞]


间隙锁(也叫 Gap 锁)和 next-key 锁的区别在于加锁的范围,间隙锁只锁定两个索引之间的援用间隙,而 next-key 锁会锁定多个索引区间,它包含「记载锁」和「间隙锁」。所以,当我们运用了范围查询,不只仅命中了已存在的 Record 记载,还包含了 Gap 间隙。

总结

固然在 InnoDB 引擎中经过间隙锁和 next-key 锁的方式处理了幻读问题,但是加锁之后会影响到数据库的并发性能,因而,假如对性能请求较高的业务场景中,倡议把隔离级别设置成 RC(READ COMMITTED),这个级别中不存在间隙锁,但是需求思索到幻读问题会招致的数据分歧性。


SpringCloudalibaba+Vue开发仿社交小程序-旧隐辞函谷,新章出汉闱的评论 (共 条)

分享到微博请遵守国家法律