1. 什么是MVCC
口述:MVCC其实他是解决这种读-写的情况的,当然读-写也可以用 锁来实现,MVCC实现的话更加高效,用锁的话其实就是相当于串行的执行,读完才能写或者写完才能读。那MVCC其实它可以读写并存,就解决了读以提交和不可重复读的问题,其实MVCC在读的时候会生成readView这里的话其实对应不同隔离级别下生成的策略也是不同的,其实也是为了解决这个可不可以重复读和幻读问题的,要是在读已提交隔离级别下那么只要select就会生成readview,也正是因为这样,可能导致幻读,在可重复读隔离级别下,一个事务select只会生成一个select,所以这个时候只有第一个select会生成readview,readview里面又记录了当前活跃的事务id,那我之后再查询的事务也是以这个readview里面的活跃事务id为参考,然后再到undo log中去找,即使可能这个第一次到第二次的期间内有属于这个活跃事务列表中的事务进行了提交,但我认为你还是没有提交的,因为我的这个readview是根据第一次的select生成的,所以我在undo log 中一查,哎你的事务id在我的活跃列表中,你的操作可能会影响到我,我不读你,我再读当前undo log的前一个undo log,我再去判断,直到找到比这个活跃列表中的事务id小的那一条行记录,正因为这样,也就解决了幻读,不管一个事务有多少个select,我select到的和一个select的是一样的,不会存在select后发现怎么多了几行记录的情况。
在当前事务根据readView里面的信息去这条记录的回滚指针里面去找undo log,读到历史版本,其实这里的话就是比如select语句要执行时,innodb会将这个时刻系统中活跃的事务id记录到redaview中,因为当前读而这个时刻活跃的事务可能会影响自己,我正在读而你在修改还没提交,就会造成我的不可重复读和幻读,所以我吧这些东西记录在readview中,由readview记录的信息再去undo log中找属于我这个事务的历史版本。
2. 快照读和当前读
读取的是快照数据。 不加锁的简单的 SELECT 都属于快照读 ,即不加锁的非阻塞读,快照读的实现是基于MVCC
对数据进行增删改都会进行当前读,都会加锁
3. 复习
在MySQL中,默认的隔离级别是可重复读,就可以解决幻读问题,使用的就是MVCC,
也是乐观锁体现。
隐藏字段、Undo Log版本链:
4. MVCC实现原理之ReadView
MVCC 的实现依赖于: 隐藏字段、Undo Log、Read View 。