14.2.2.5 幻象读

所谓的幻象读发生在事务当相同的查询产生不同的结果集在不同的时间,比如

如果SELECT 执行两次,但是第2次返回和第一次返回时不相等的,这个记录称为 幻象行。

假设 这里有一个index 在child 表的id列,你需要读和lock 所有的记录 值大于100,

意向更新一些列在选择的记录后。

SELECT * FROM child WHERE id > 100 FOR UPDATE;

查询扫描index 从第一个记录 id是大于100开始。 如果表包含记录有id值在90和102.

如果locks 设置在index records 在扫描范围 不允许插入在gaps 区间(在这种情况下, gap 区间是90到102)

另外的会话是插入一个新的记录到表 值为101.

如果你执行相同的SELECT 在相同的事务里,你会看到一个一个新的记录id=101(一个幻读)

查询返回的结果。如果我把一组数据集称为数据项,

新的幻象child 会违反事务的隔离机制,一个事务可以运行在它的事务期间数据没有改变。

为了防止幻读,InnoDB 使用一个算法称为next-key locking 组合index-row locking 和gap locking.

InnoDB 执行row-level locking 以这样的方式 当它搜索或者扫描一个表的索引,

它设置共享的或者排它锁 在index records 它遇到的。因此,row-level locks 实际是index-record locks.

因此,一个next-key lock 在一个index record locks 也影响”gap” 在那个index record.

也就是说,一个next-key lock 是一个Index-record lock 加上一个gap lock 在gap index record 之前。

如果一个会话有一个共享锁或者排它锁在记录R,另外的会话不能插入一个新的index record 在这个区间

立即在R 顺序前。

当InnoDB 扫描索引时,它可以锁住区间在最后的记录 在索引里,就像前面发生的例子:

为了防止任何的插入 ,id值大于100, InnoDB设置的locks 包括一个lock 在区间。

你可以使用next-key locking 来应用一个唯一检查在你的应用。

如果你读你的数据在共享模式和不会看到重复对于一条你要插入的记录,

你可以安全的插入你的记录和知道next-key lock 设置在你的记录的继承者 在读阻止任何其他插入一个重复值。

原文地址:https://www.cnblogs.com/hzcya1995/p/13351206.html