温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

InnoDB怎么解决幻读问题

发布时间:2023-05-09 14:46:01 来源:亿速云 阅读:114 作者:iii 栏目:开发技术

这篇“InnoDB怎么解决幻读问题”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“InnoDB怎么解决幻读问题”文章吧。

事务隔离级别

事务隔离是数据库处理的基础之一,是 ACID 中的 I。在 MySQL 的 InnoDB 引擎中支持在 SQL:1992 标准中的四种事务隔离级别,如下图所示,其中 P1 表示脏读(Dirty read),P2 表示不可重复读(Dirty read),P3 表示幻读(Phantom)。

InnoDB怎么解决幻读问题

为什么需要定义这么多隔离呢?从上图中也能猜出一二了,InnoDB 提供多个隔离级别主要原因是:让使用者可以在多个事务同时进行更改和执行查询时微调性能与结果的可靠性、一致性和可再现性之间的平衡的设置。是一种性能与结果可靠性间的 trade off

什么是幻读

在聊「InnoDB 解决幻读方式」前我们需要先了解幻读是什么,官方文档的描述如下:

A row that appears in the result set of a query, but not in the result set of an earlier query.

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

InnoDB怎么解决幻读问题

InnoDB 解决幻读方式

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

InnoDB怎么解决幻读问题

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

select * from user where id = 9527 for update;

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

InnoDB怎么解决幻读问题

在被锁定的记录(这里是 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)这个开区间范围的索引加间隙锁。

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

InnoDB怎么解决幻读问题

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

select * from user where id > 9530 for update;

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

InnoDB怎么解决幻读问题

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

(9530,9535] (9535,9540] (9540,+&infin;]

InnoDB怎么解决幻读问题

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

以上就是关于“InnoDB怎么解决幻读问题”这篇文章的内容,相信大家都有了一定的了解,希望小编分享的内容对大家有帮助,若想了解更多相关的知识内容,请关注亿速云行业资讯频道。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI