1、概念

MVCC:Multi-Version Concurrency Control,多版本并发控制。为了提高数据库的并发性能,用更好的方式去处理读-写冲突,做到即使有读写冲突时,也能做到不加锁,非阻塞并发读。

mysql中分为当前读和快照读:

(1)当前读:读取的是记录的最新版本,读取时还要保证其他并发事务不能修改当前记录,会对读取的记录进行加锁

(2)快照读:不加锁的查询操作就是快照读,即不加锁的非阻塞读;快照读的前提是隔离级别不是串行级别,串行级别下的快照读会退化成当前读

快照读是基于提高并发性能的考虑,快照读的实现是基于多版本并发控制,即MVCC,在很多情况下,避免了加锁操作,降低了开销;既然是基于多版本,即快照读可能读到的并不一定是数据的最新版本,而有可能是之前的历史版本

2、MVCC实现原理

实现原理主要是依赖记录中的 3个隐式字段undo日志 ,Read View

(1)每行记录除了我们自定义的字段外,还有数据库隐式定义的几个字段

DB_TRX_ID
最近修改(修改/插入)事务ID:记录创建这条记录/最后一次修改该记录的事务ID
DB_ROLL_PTR
回滚指针,指向这条记录的上一个版本(存储于rollback segment里)
DB_ROW_ID
隐含的自增ID(隐藏主键),如果数据表没有主键,InnoDB会自动以DB_ROW_ID产生一个聚簇索引

(2)undo日志

数据修改后产生的一个数据拷贝副本,DB_ROLL_PTR回滚指针指向的就是这个副本,例如下面例子修改name字段

mysql 快照读 数据不对怎么办 mysql快照读怎么实现的_字段

(3)Read view

Read view主要是用来做可见性判断的, 即当我们某个事务执行快照读的时候,对该记录创建一个Read View读视图,把它比作条件用来判断当前事务能够看到哪个版本的数据,既可能是当前最新的数据,也有可能是该行记录的undo log里面的某个版本的数据。Read view视图中的数据是通过三个隐藏字段和undo日志,然后遵循一个可见性的算法,生成的当前事务可见的一个数据视图。

RC隔离级别下,是每个快照读都会生成并获取最新的Read View;而在RR隔离级别下,则是同一个事务中的第一个快照读才会创建Read View, 之后的快照读获取的都是同一个Read View。