MVCC (Multi多-Version版本 Concurrency并发性 Control控制)多版本并发控制。
想要理解MVCC要先清楚她是干什么用的在哪里用的:MVCC应用在MySQL事务隔离级别中读已提交(RC)和可重复读(RR)两个级别中,用来解决“不可重复读”这个问题。所谓多版本并发控制,指的是一条记录经过多次修改会有多个版本,每次的修改都会有一个记录,多个版本串联起来形成一条版本链,MVCC的过程,本质就是访问版本链,并判断哪个版本可见的过程。该判断算法是通过版本上的trx_id与快照ReadView的若干个信息进行对比。
MVCC实现原理
MVCC实现原理主要是由三个隐藏字段、undo log、read view这三个部分来实现的。
三个隐藏字段
- DB_TRX_ID:事务中对某条记录做增删改时,就会将这个事务的事务ID写入到trx_id中
- DB_ROLL_PTR(pointer):指向undo log的指针
- DB_ROW_ID:隐藏的主键
Undo log(回滚日志)版本链
Read View 一致性读视图
Read View简单理解就是对数据在每个时刻的状态拍成照片记录下来。那么之后获取某时刻的数据时就还是原来的照片上的数据,是不会变的.
Read View中比较重要的字段有4个:
- creaor_trx_id:当前事务的ID
- m_ids:生成readview时还在活跃的事务ID集合,就是正在执行还未提交的事务ID列表
- min_trx_id:正在执行的最小事务id,也就是m_ids中的最小值
- max_trx_id:最大事务ID,下一个要生成的事务ID
通过Read View 如何判断可不可以读到:
- trx_id = creator_trx_id :就是访问的当前修改记录 可读
- trx_id < min_trx_id :表明生成该版本的事务在当前事务生成readview前已经提交 可读
- trx_id >= max_trx_id :表明生成该版本的事务在当前事务生成readview后才开启 不可读
- min_trx_id <trx_id < max_trx_id:判断是否在集合列表中,在就不可读,不在就可读
何时生成ReadView快照
-
在 读已提交(Read Committed, 简称RC) 隔离级别下,在一个事务中,每一次读取数据前都生成一个ReadVIew。
-
在 可重复读 (Repeatable Read,简称RR)隔离级别下,在一个事务中,只在 第一次读取数据前生成一个ReadVIew。
快照读(Snapshot Read
)与当前读 (Current Read
)
在 MVCC 并发控制中,读操作可以分为两类: 快照读(Snapshot Read
)与当前读
-
快照读 快照读是指读取数据时不是读取最新版本的数据,而是基于历史版本读取的一个快照信息(mysql读取undo log历史版本) ,快照读可以使普通的SELECT 读取数据时不用对表数据进行加锁,从而解决了因为对数据库表的加锁而导致的两个如下问题
-
解决了因加锁导致的修改数据时无法对数据读取问题.
-
解决了因加锁导致读取数据时无法对数据进行修改的问题.
-
-
当前读 当前读是读取的数据库最新的数据,当前读和快照读不同,因为要读取最新的数据而且要保证事务的隔离性,所以当前读是需要对数据进行加锁的(
Update delete insert select ....lock in share mode
,select for update
为当前读)
总结
-
并发环境下,写-写操作有加锁解决方案,但为了提高性能,InnoDB存储引擎提供MVCC,目的是为了解决读-写,写-读操作下不加锁仍能安全进行。
-
MVCC的过程,本质就是访问版本链,并判断哪个版本可见的过程。该判断算法是通过版本上的trx_id与快照ReadView的若干个信息进行对比。
-
MVCC的过程,本质就是访问版本链,并判断哪个版本可见的过程。该判断算法是通过版本上的trx_id与快照ReadView的若干个信息进行对比。