Multi-Version Concurrency Control 多版本并发控制机制,本文摘自一下文章。
数据库内核月报 - 2017 / 12
MVCC底层原理讲解
InnoDB MVCC 机制
多版本控制: 指的是一种提高并发的技术。
最早的数据库系统,只有读读之间可以并发,读写,写读,写写都要阻塞。引入多版本之后,只有写写之间相互阻塞,其他三种操作都可以并行,这样大幅度提高了InnoDB的并发度。
在内部实现中,InnoDB是在undolog中实现的,通过undolog可以找回数据的历史版本。找回的数据历史版本可以提供给用户读(按照隔离级别的定义,有些读请求只能看到比较老的数据版本),也可以在回滚的时候覆盖数据页上的数据。在InnoDB内部中,会记录一个全局的活跃读写事务数组,其主要用来判断事务的可见性。
1、 MVCC 运行在 RC 和 RR 这两个隔离级别下
1、针对RC隔离级别,事务中的每个查询语句都单独构建一个readview,所以如果两个查询之间有事务提交了,两个查询读出来的结果就不一样。
2、针对RR隔离级别,在第一次创建readview后,这个readview就会一直持续到事务结束,也就是说在事务执行过程中,数据的可见性不会变,所以在事务内部不会出现不一致的情况。
从这里可以看出,在InnoDB中,RR隔离级别的效率是比RC隔离级别的高。
3、针对RU隔离级别,由于不会去检查可见性,所以在一条SQL中也会读到不一致的数据。
4、针对串行化隔离级别,InnoDB是通过锁机制来实现的,而不是通过多版本控制的机制,所以性能很差。
2、事务
在InnoDB里面有两种事务,一种是读写事务
,就是会对数据进行修改的事务,另外一种是只读事务
,仅仅对数据进行读取。
读写事务需要比只读事务多做以下几点工作:首先,需要分配回滚段,因为会修改数据,就需要找地方把老版本的数据给记录下来,其次,需要通过全局事务id产生器产生一个事务id
,最后,把读写事务加入到全局读写事务链表(trx_sys->rw_trx_list),把事务id加入到活跃读写事务数组中(trx_sys->descriptors)。因此,可以看出,读写事务确实需要比只读事务多做不少工作,在使用数据库的时候尽可能把事务申明为只读。
3、ReadView
在RR隔离级别下,第一次查询时候创建ReadView ;
在RC隔离级别下,每次查询都会创建ReadView 。
原理概括
自己的概括,可能不太准确
通过新增回滚指针(DATA_ROLL_PTR)字段组织 undo log 中的内容形成版本链。
通过新增事务 ID字段结合 ReadView 判断版本链中各个版本事务可见可见性。
MVCC机制有什么问题?怎么去解决这个问题