1、什么是幻读在一个事务中,经过多次查询,结果集数量不一致的情况称为幻读。而多出或少出的线称为虚线。2、为什么要解决幻读?在高并发的数据库系统中,需要保证事务之间的隔离和事务本身的一致性。3、MySQL如何解决幻读?如果你读了这篇文章,那么我假设你了解脏读、不可重复读和可重复读。1、多版本并发控制(MVCC)(快照读/一致性读)大多数数据库都实现了多版本并发控制,都是通过保存数据快照来实现的。以InnoDB为例,每行有两个分词冗余。一个是行的创建版本,一个是行的删除(过期)版本。具体版本号(trx_id)存在于information_schema.INNODB_TRX表中。每次打开事务时,版本号(trx_id)都会递增。事务每次取数据,取创建版本小于当前事务版本的数据,过期版本大于当前版本的数据。普通select是snapshotread。select*fromTwherenumber=1;原理:保存历史数据的快照,因此其他事务增删数据,对当前事务不可见。2.Next-keylock(currentread)next-keylock由两部分组成:Recordlock(rowlock)GaplockRecordlock是加在索引上的锁,gaplock加在索引之间。(思考:如果列上没有索引会怎样?)select*fromTwherenumber=1forupdate;select*fromTwherenumber=1lockinsharemode;insertupdatedelete原理:锁定当前数据行与上一条数据和下一条数据的间隙,保证在这个范围内读取的数据是一致的。其他:MySQLInnoDB引擎的RR隔离级别是否解决了幻读?引用github上的一个评论地址:Mysql官方对幻读的解释是:只要一个事务中第二次select的行数多了,就认为是幻读。先选中a事务,b事务insert确实会加gap锁,但是如果b事务commit,gap锁就会释放(释放后,a事务可以dml随意操作),a重选的结果MVCC下会返回第一个select一样,然后无条件更新一个事务。这个update会作用于所有的行(包括b事务新添加的),当一个事务再次select的时候b事务中会出现一个新的行,并且这个新的行已经被update修改过,在RR处确实是这样的等级。如果这么理解的话,Mysql的RR级别还真的防不了幻读。在当前读的情况下,mysql使用next-key来避免幻读。select*fromtwherea=1;属于snapshotreadselect*fromtwherea=1lockinsharemode;属于currentread不能认为snapshotread和currentread的结果是phantomread,这是两种不同的用途。所以我觉得mysql的rr级别解决了幻读。先说结论,MySQL存储引擎InnoDB隔离级别RR解决幻读问题。面试问的是烂MySQL的四种隔离级别。本文推荐大家阅读。在引用的一个问题中提到,T1中select之后的update会把T2中insert的数据一起更新,所以认为多了一行,所以无法防止幻读。看似说法无懈可击,实则大错特错。InnoDB有快照读取和当前读取两种模式。如果只有快照读,那么不会出现幻读问题,但是如果语句升级为当前读,那么T1inselect有时需要使用如下语法:select*fromtforupdate(lockinsharemode)进入当前读数,自然没有T2可以插入数据。注意,虽然next-key很好的解决了幻读问题,但是它还是遵循一般规律,隔离级别越高,并发越低。
