MySQL是如何解决幻读

MySQL通过快照读和当前度两种模式解决幻读问题。

快照读:read view版本链中的数据,不会因为其它事务的提交或者未提交影响事务对同一张表的查询结果(遵循多版本并发控制规则)

当前读是基于 临键锁(行锁 + 间歇锁)来实现的,适用于 insert,update,delete, select … for update, select … lock in share mode 语句,以及加锁了的 select 语句。

在可重复读隔离级别下,普通的查询是快照读,是不会看到别的事务插入的数据的。因此,幻读在“当前读”下才会出现。

MySQL幻读解决方式

间隙锁(Gap Lock):锁加在不存在的空闲空间,可以是两个索引记录之间,也可能是第一个索引记录之前或最后一个索引之后的空间。
Next-Key Lock:行锁与间隙锁组合起来用就叫做Next-Key Lock。

当我们用范围条件而不是相等条件检索数据,并请求共享或排他锁时,InnoDB会给符合条件的已有数据记录的索引项加锁;对于键值在条件范围内但并不存在的记录,叫做“间隙(GAP)”,InnoDB也会对这个“间隙”加锁,这种锁机制就是所谓的间隙锁(Next-Key锁)。

innodb的默认事务隔离级别是rr(可重复读)。它的实现技术是mvcc(MVCC只在读提交可重复读两种隔离级别下工作)。基于版本的控制协议。该技术不仅可以保证innodb的可重复读,而且可以防止幻读。但是它防止的是快照读,也就是读取的数据虽然是一致的,但是数据是历史数据。

当前读最新数据-next-key lock

如何做到保证数据是一致的(也就是一个事务,其内部读取对应某一个数据的时候,数据都是一样的),同时读取的数据是最新的数据。innodb提供了next-key lock,也就是结合gap锁与行锁达到最终目的。