MySQL解决幻读(2)
MySQL的默认隔离级别(REPEATABLE-READ)如何解决脏读和不可重复度
脏读
读取到未提交的数据
不可重复度
两次读取的数据不一致,侧重与数据的更新
幻读
两次读取的数据不一致,侧重数据的新增和删除
解决
根据当前读
或 MVCC
来解决脏读和不可重复读的
当前读:
加锁,在读取时会将所有数据加锁,所以再次读取的时候因为这些数据加了锁,读取到的数据就可重复读。但是锁只能保护已经存在的数据,无法防止其他事务插入新的数据。所以,如果在一个事务中,你先执行了一个当前读操作,然后另一个事务插入了一个新的记录,当你再次执行当前读操作时,就可能会看到这个新插入的“幻影”记录。
MVCC:
多版本并发控制,是根据多版本的快照来实现的。一个事务在开始时会创建一个快照,意味着在这个事务的整个生命周期内,它所看到的数据都是一致的,这个数据是在事务开始时的快照,不能看到在事务执行过程中其他事务插入的新数据。但是当事务中包含更新操作时,这些操作会读取最新的数据,而非快照中的数据。也就是说,这些操作可以看到其他事务新插入的数据。
MySQL使用MVCC和间隙锁来解决幻读
间隙锁:
间隙锁不是锁定记录本身,而是锁定记录之间的“间隙”。在REPEATABLE-READ隔离级别下,InnoDB会使用间隙锁来防止其他事务在这个间隙中插入新的记录,从而确保事务的一致性。
例如,如果你在一个事务中查询了某个范围的记录,InnoDB不仅会对查询到的记录加锁,还会对这些记录之间和周围的间隙加锁,这样就可以防止其他事务在这个范围内插入新的记录,从而避免了幻读的产生。