一、当前读
读取的是记录的最新版本,读取时还要保证其他并发事务不能修改当前记录,会对读取的记录进行加锁。对于我们日常的操作,如:select … lock in share mode(共享锁),select … for update、update、insert、delete(排他锁)都是一种当前读。
测试:
但如果第二次查询的时候没有加上 lock in share mode
,就算右侧事务提交了,实际上也不能查到,原因是因为当前隔离级别是Repeatable Read,即可重复读。那也就意味着现在select语句不是当前读,但如果要执行当前读,可以在select后面加上 lock in share mode
,或者 for update
,加上锁之后就变成了当前读。
在测试中我们可以看到,即使是在默认的RR隔离级别下,事务A中依然可以读取到事务B最新提交的容,因为在查询语句后面加上了 lock in share mode 共享锁,此时是当前读操作,可以读取到最新的数据。当然,当我们加排他锁的时候,也是当前读操作。
二、快照读
简单的select(不加锁)就是快照读,快照读,读取的是记录数据的可见版本,有可能是历史数据, 不加锁,是非阻塞读。
- Read Committed:每次select,都生成一个快照读。
- Repeatable Read:开启事务后第一个select语句才是快照读的地方,后续我们在查的时候,实际上直接查的就是前面产生的这个快照数据。
- Serializable:快照读会退化为当前读,每一次的读取操作都会加锁。
测试:
在测试中,我们看到即使事务B提交了数据,事务A中也查询不到。 原因就是因为普通的select是快照读,而在当前默认的RR隔离级别下,开启事务后第一个select语句才是快照读的地方,后面执行相同 的select语句都是从快照中获取数据,可能不是当前的最新数据,这样也就保证了可重复读。
三、MVCC
全称 Multi-Version Concurrency Control
,多版本并发控制。指在InnoDB引擎中它会去维护一个数据的多个版本, 使得读写操作没有冲突,快照读为MySQL实现MVCC提供了一个非阻塞读功能。MVCC的具体实现,还需要依赖于数据库记录中的三个隐式字段、undo log日志、readView。
接下来,我们再来介绍一下InnoDB引擎的表中涉及到的隐藏字段 、undolog 以及 readview,从 而来介绍一下MVCC的原理。