InnoDB实现MVCC
InnoDB实现的MVCC实际上也就是实现了一致性非锁定读,我理解是基于乐观锁的思想。概括的来说也就是当一行数据某些正在进行Insert Update Delete操作的时候,有一个事务需要读取当前这行数据,并不会等待其他事务操作结束后读取数据,而是采用快照读的方式,读取undolog日志中先前版本的数据。
对于不同事务级别实现MVCC的做法也是不一样的,下面介绍一下RC(read commited)与RR(repeat read)事务隔离级别下MVCC是如何实现的
首先讲讲他们的相同点,从undolog日志中读取旧版本数据
undolog日志很多人只认为他只能用于事务回滚,保持事务的原子性。但是MVCC的核心之一也就在于undolog
在undolog日志中基于了对数据进行写操作的事务id,并且每条undolog日志中的日志都维护了一个指针指向上一个版本的数据。(对于最原始的一条数据 id = null , 指向 = null)
有个undolog日志我们也就得到了旧版数据的记录,那我们如何判断当前快照读操作一个使用哪一条数据呢?
MVCC的另外一个核心 read View 读视图也就应运而生了,这也是不同RC与RR隔离级别下差别最大的地方
首先来介绍一下Read View中的几个核心参数
1.活跃事务Id数组
2.最小活跃事务id
3.预生成事务id
4.当前Read View Id(便于更新Read View)
在进行快照读的时候根据几个筛选条件来选择出可以被访问的事务id,然后到undoLog下找到对应事务id的数据访问。我理解筛选条件其实也就是筛选出最新的已经提交的事务
在RC隔离级别下,读事务中每次读取数据都会生成一个全新的Read View。可以解决脏读问题,因为每次都只会读取已经提交的数据,但是无法解决不可重复度问题。因为每次读取新数据都会生成一个新的Read View视图,如果在本次读事务中两次快照读过程中有一个新的写操作提交,就会读到这个新提交后的数据,因为它此时已经变成最新的已提交事务。会出现两次读操作读到的数据不一致的情况(不可重复读)
在RR隔离级别下,在一次读事务中只会创建一个Read View视图,后面的快照读全部都是复用这个Read View视图解决了不可重复读的问题,也一定程度上解决了幻读的问题。所以在MySQL5.0后数据库的默认隔离级别为RR