🗒️Day86【概念解析】Phantom Rows
00 分钟
2023-12-16
2023-12-20
type
status
date
slug
summary
tags
category
icon
password

整理定义

幻影行Phantom Rows):所谓的幻影问题是指在一个事务中,同一查询在不同时间产生不同的行集。例如,如果一个SELECT被执行两次,但第二次返回了第一次未返回的行,那么这个行就是一个“幻影”行。这个问题就是幻读问题。

复述展开

假设在child表的id列上有一个索引,你想读取并锁定所有id值大于100的行,然后打算稍后更新选定行中的某个列:
该查询从id大于100的第一条记录开始扫描索引。假设表中有id值为90和102的行。如果在扫描范围内设置的索引记录上的锁没有锁定插入到间隙中的记录(在这种情况下,间隙在90和102之间),那么另一个会话可以在表中插入一个新行,id为101。如果你在同一事务中执行相同的SELECT,你会在查询返回的结果集中看到一个新的id为101的行(一个“幻影”)。如果我们把一组行看作一个数据项,新的幻影子项将违反事务的隔离原则,即一个事务应该能够运行,使得它读取的数据在事务期间不会改变。
为了防止幻影,InnoDB使用了一种称为next-key locking的算法,该算法将索引行锁定与间隙锁定结合起来。InnoDB执行行级锁定的方式是,当它搜索或扫描表索引时,它在遇到的索引记录上设置共享或独占锁。因此,行级锁实际上是索引记录锁。此外,对索引记录的next-key锁也影响到索引记录前的“间隙”。也就是说,next-key锁是索引记录锁加上在索引记录前的间隙锁。如果一个会话在索引中的记录R上有一个共享或独占锁,那么另一个会话不能在索引顺序中R之前的间隙中插入一个新的索引记录。
当InnoDB扫描索引时,它也可以锁定索引中最后一条记录后的间隙。就像在前面的例子中发生的那样:为了防止任何插入到表中的id值大于100的记录,InnoDB设置的锁包括在id值102后面的间隙上的锁。
你可以使用next-key锁定在你的应用中实现唯一性检查:如果你以共享模式读取你的数据,并且没有看到你要插入的行的重复项,那么你可以安全地插入你的行,并知道在读取过程中在你的行的后继上设置的next-key锁阻止了任何人同时插入你的行的重复项。因此,next-key锁定使你能够在你的表中“锁定”某物的不存在。
间隙锁定可以被禁用,这可能会导致幻影问题,因为当间隙锁定被禁用时,其他会话可以在间隙中插入新的行。

理解体会

幻影行问题是指在同一事务中,同一查询在不同时间产生不同的行集。为了防止这种情况,InnoDB使用了一种称为next-key locking的算法,该算法将索引行锁定与间隙锁定结合起来。这种锁定方式可以防止在事务期间插入新的行,从而保证了数据的一致性。然而,如果禁用了间隙锁定,可能会导致幻影问题,因为其他会话可以在间隙中插入新的行。
Next-key锁定可以用于实现唯一性检查,即在插入新行之前,先以共享模式读取数据,如果没有发现要插入的行的重复项,那么就可以安全地插入新行。这是因为在读取过程中,对你的行的后继设置的next-key锁阻止了其他人同时插入你的行的重复项。这样,next-key锁定使你能够在你的表中“锁定”某物的不存在。
总的来说,InnoDB的next-key锁定算法通过锁定索引记录和前后的间隙,有效地解决了幻影行问题,保证了事务的隔离性和数据的一致性。但是,如果禁用了间隙锁定,可能会导致幻影问题,因为其他会话可以在间隙中插入新的行。
📌
快速跳转链接
【概念解析】启动
【概念解析】Day 1 - 10
【概念解析】Day 11 - 20
【概念解析】Day 21 - 30
【概念解析】Day 31 - 40
【概念解析】Day 41 - 50
【概念解析】Day 51 - 60
【概念解析】Day 61 - 70
【概念解析】Day 71 - 80
【概念解析】Day 81 - 90
 
上一篇
Day87 【概念解析】MySQL死锁实例
下一篇
Day85【概念解析】Deadlocks in InnoDB

评论
Loading...