定义
-
MVCC
MVCC
,全称Multi-Version Concurrency Control
,即多版本并发控制。MVCC是一种并发控制的方法,一般在数据库管理系统中,实现对数据库的并发访问,在编程语言中实现事务内存。在MySQL,
MVCC
并不是Server级别的实现,而是InnoDB引擎的实现。 -
快照读
像不加锁的select操作就是快照读,即不加锁的非阻塞读;快照读的前提是隔离级别不是串行级别,串行级别下的快照读会退化成当前读;之所以出现快照读的情况,是基于提高并发性能的考虑,快照读的实现是基于多版本并发控制,即MVCC,可以认为MVCC是行锁的一个变种,但它在很多情况下,避免了加锁操作,降低了开销;由于是基于多版本,即快照读可能读到的并不一定是数据的最新版本,而有可能是之前的历史版本。 -
当前读
像select lock in share mode(共享锁), select for update ; update, insert ,delete(排他锁)这些操作都是一种当前读,为什么叫当前读?就是它读取的是记录的最新版本,读取时还要保证其他并发事务不能修改当前记录,会对读取的记录进行加锁。 -
幻读
事务A 按照一定条件进行数据读取, 期间事务B 插入了相同搜索条件的新数据,事务A再次按照原先条件进行读取时,发现了事务B 新插入的数据,这种情况称为幻读。
注意:幻读特指新插入的数据。如果事务A 按一定条件搜索, 期间事务B 删除了符合条件的某一条数据,导致事务A再次读取时数据少了一条。这种情况归为不可重复读。
什么情况下会出现幻读?
全部使用快照读
这种情况是最简单的。由于MVCC机制的存在,每个事务开始的时候读取的都是固定的版本的数据。很明显这种情况是不会出现幻读的。
全部使用当前读
由于MySQL间隙锁读存在,后执行的事务会被之前运行的事务阻塞。即退化到串形执行。这种情况也不会存在幻读情况
当前读快照读混用
准备数据
CREATE TABLE `author` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
`age` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8;
INSERT into author VALUES (1,'g1',20),(5,'g5',20),(15,'g15',30),(20,'g20',30);
运行:
时间 | 事务1 | 事务 2 |
---|---|---|
begin | begin | |
T1 | Select * from author where age =20; 结果:(1,‘g1’,20),(5,‘g5’,20) | |
T2 | insert into author values (25,‘g25’,20) | |
T3 | select * from author where age =20; 此时结果仍为:(1,‘g1’,20),(5,‘g5’,20) | |
T4 | Update author set name =‘update’ where age =20; 此时显示受影响三行。 | |
T5 | Select * from author where age =20; 结果:(1,‘update’,20),(5,‘update’,20),(25,‘update’,20) |
可以发现这种混用的情况是会出现幻读的。
结论
可重复读隔离级别下,一个事务中只使用当前读,或者只使用快照读都能避免幻读。如果当前读和快照读混用的话就不能保证不出现幻读。