所谓的幻影问题发生在一个事务时相同的查询生成在不同的时间不同的行。例如,如果一个选择
执行两次,但第二次返回一个行不是第一次返回,行是吗”幻影”行。
假设上有一个索引id
列的孩子
表,你要读的书和锁从表中所有行有一个标识符值大于100,打算更新一些列选中的行后:
SELECT *从孩子id > 100更新;
扫描索引的查询从第一条记录开始id
比100年大。让表包含行id
90年和102年的值。如果锁设置索引记录的扫描范围不锁定插入的空白(在这种情况下,90年和102年之间的差距),另一个会话可以向表中插入一个新行id
101股。如果你要执行相同的选择
在同一事务中,你会看到一个新行id
101 (”幻影”在查询返回的结果集。如果我们把一组行作为一个数据项,新幻孩子将违反交易事务的隔离原理应该能够运行,这样的数据读事务不会改变。
为了防止幻影,InnoDB
使用一个算法称为第二个关键锁定结合index-row锁锁定与差距。InnoDB
执行行级别锁定以这样一种方式,当它搜索或扫描表索引,它集共享或专用锁在它遇到的索引记录。因此,行级锁实际上是索引记录锁。此外,第二个关键锁定一个索引记录也会影响的”差距”在索引记录。,第二个关键锁是一个索引记录锁+一个缺口锁之前的差距指数记录。如果一个会话共享或独占锁R
在索引,另一个会话不能插入一个新的索引记录之前的差距R
在索引中。
当InnoDB
扫描索引,它还可以锁定后记录的差距指数。只是发生在前面的例子:防止插入到表中id
将大于100,设定的锁吗InnoDB
包括一个锁定后的差距id
价值102。
您可以使用键锁定在应用程序中实现唯一性检查:如果你读数据共享模式和没有看到你要复制的行插入,那么您可以安全地插入行和知道第二个关键锁上设置的继任者行读期间阻止任何人同时插入的重复行。因此,第二个关键锁定支持你”锁”你的表中不存在的东西。
锁定的差距可以被禁用了部分14.7.1,“InnoDB锁定”。这可能导致幽灵的问题因为其他会话时可以插入新行差距差距锁定是禁用的。