Mysql_幻影读

131 阅读3分钟

幻影读

当同一查询在不同时间产生不同的行集时,在事务内就会发生 所谓的幻像问题。例如,如果一个 SELECT执行两次,但是第二次返回的行却不是第一次返回,则该行是“ phantom ”行。

假设idchild表的列上有一个索引,并且您想要读取和锁定该表中所有标识符值大于100的行,以期稍后更新所选行中的某些列:

SELECT * FROM child WHERE id > 100 FOR UPDATE;

该查询从id大于100的第一条记录开始扫描索引 。让表包含具有id90和102值的行。如果在扫描范围内对索引记录设置的锁定不锁定在间隙中插入的内容(在这种情况下,即90和102之间的间隔),另一个会话可以在表中插入一个新行,其行号为 id101。如果要SELECT在同一事务中执行相同 的操作,则会看到一个新行,其行号id为101(一个 “幻影”)查询返回的结果集中。如果我们将一组行视为数据项,则新的幻影子级将违反事务应能够运行的事务隔离原则,以使已读取的数据在事务期间不会更改。

为了防止产生幻影,请InnoDB使用称为“下一键锁定”的算法,该算法将索引行锁定与间隙锁定结合在一起。 InnoDB执行行级锁定的方式是,当它搜索或扫描表索引时,会在遇到的索引记录上设置共享或互斥锁。因此,行级锁实际上是索引记录锁。此外,索引记录上的下一键锁定也会影响该索引记录之前的 “间隙”。即,下一键锁定是索引记录锁定加上索引记录之前的间隙上的间隙锁定。如果一个会话记录了共享或独占锁R在索引中,另一个会话不能R在索引顺序之前的间隙中插入新的索引记录 。

InnoDB扫描索引,它也可以锁定在指数的最后一个记录之后的间隙。在前面的示例中恰好发生了这种情况:为了防止在表中插入任何 id大于100的内容,设置的锁 InnoDB包括在id值102之后的间隙上的锁 。

您可以使用下一键锁定在应用程序中实现唯一性检查:如果您以共享模式读取数据,但没有看到要插入的行的重复项,则可以安全地插入行并知道在读取期间在行的后继上设置的next键锁可以防止任何人同时为行插入重复项。因此,下一键锁定使您可以“锁定”表中不存在的内容。

“ InnoDB锁定”中所述,可以禁用间隙锁定 。这可能会导致幻影问题,因为在禁用间隙锁定时,其他会话可以在间隙中插入新行。

更多内容欢迎关注我的个人公众号“韩哥有话说”,100G人工智能学习资料,大量后端学习资料等你来拿。

qrcode_for_gh_3214f9e3470a_258.jpg