mvcc如何实现

MySQL的innodb引擎是如何实现MVCC的。innodb会为每一行添加两个字段,分别表示该行建立的版本删除的版本,填入的是事务的版本号,这个版本号随着事务的建立不断递增。在repeated read的隔离级别(事务的隔离级别请看这篇文章)下,具体各类数据库操做的实现:mysql

select:知足如下两个条件innodb会返回该行数据:(1)该行的建立版本号小于等于当前版本号,用于保证在select操做以前全部的操做已经执行落地。(2)该行的删除版本号大于当前版本或者为空。删除版本号大于当前版本意味着有一个并发事务将该行删除了。sql

即  能够查到的知足的条件 :该行的建立的版本号=<当前事务的版本号<该行的删除版本号数据库

insert:将新插入的行的建立版本号设置为当前系统的版本号。并发

delete:将要删除的行的删除版本号设置为当前系统的版本号。mvc

update:不执行原地update,而是转换成insert + delete。将旧行的删除版本号设置为当前版本号,并将新行insert同时设置建立版本号为当前版本号。性能

其中,写操做(insert、delete和update)执行时,须要将系统版本号递增。大数据

因为旧数据并不真正的删除,因此必须对这些数据进行清理,innodb会开启一个后台线程执行清理工做,具体的规则是将删除版本号小于当前系统版本的行删除,这个过程叫作purge。.net

经过MVCC很好的实现了事务的隔离性,能够达到repeated read级别,要实现serializable还必须加锁。线程

参考:blog

多版本并发控制技术已经被普遍运用于各大数据库系统中,如Oracle,MS SQL Server 2005+, Postgresql, Firebird, Maria等等,开源数据库MYSQL中流行的INNODB引擎也采用了相似的并发控制技术.本文就将结合实例来解析不一样事务隔离等级下INNODB的MVCC实现原理.  

 1 MVCC概述  

 1.1 MVCC简介  

 MVCC (Multiversion Concurrency Control),即多版本并发控制技术,它使得大部分支持行锁的事务引擎,再也不单纯的使用行锁来进行数据库的并发控制,取而代之的是,把数据库的行锁与行的多个版本结合起来,只须要很小的开销,就能够实现非锁定读,从而大大提升数据库系统的并发性能.   1.2 实现原理   MVCC能够提供基于某个时间点的快照,使得对于事务看来,老是能够提供与事务开始时刻相一致的数据,而无论这个事务执行的时间有多长.因此在不一样的事务看来,同一时刻看到的相同行的数据多是不同的,即一个行可能有多个版本.是否听起来难以想象呢?   原来,为了实现mvcc, innodb对每一行都加上了两个隐含的列,其中一列存储行被更新的”时间”,另一列存储行被删除的”时间”. 可是innodb存储的并非绝对的时间,而是与时间对应的数据库系统的版本号,每当一个事务开始的时候,innodb都会给这个事务分配一个递增的版本号,因此版本号也能够被认为是事务号.对于每个”查询”语句,innodb都会把这个查询语句的版本号同这个查询语句遇到的行的版本号进行对比,而后结合不一样的事务隔离等级,来决定是否返回该行.

下面分别以select、delete、 insert、 update语句来讲明:   1) SELECT   对于select语句,只有同时知足了下面两个条件的行,才能被返回:   •行的被修改版本号小于或者等于该事务号   •行的被删除版本号要么没有被定义,要么大于事务的版本号:行的删除版本号若是没有被定义,说明该行没有被删除过;若是删除版本号大于当前事务的事务号,说明该行是被该事务后面启动的事务删除的,因为是repeatable read隔离等级,后开始的事务对数据的影响不该该被先开始的事务看见,因此该行应该被返回.   2) INSERT   对新插入的行,行的更新版本被修改成该事务的事务号   3) DELETE   对于删除,innodb直接把该行的被删除版本号设置为当前的事务号,至关于标记为删除,而不是实际删除   4) UPDATE   在更新行的时候,innodb会把原来的行复制一份到回滚段中,并把当前的事务号做为该行的更新版本

1.3 MVCC的优缺点   上述策略的结果就是,在读取数据的时候,innodb几乎不用得到任何锁, 每一个查询都经过版本检查,只得到本身须要的数据版本,从而大大提升了系统的并发度.   这种策略的缺点是,为了实现多版本,innodb必须对每行增长相应的字段来存储版本信息,同时须要维护每一行的版本信息,并且在检索行的时候,须要进行版本的比较,于是下降了查询的效率;innodb还必须按期清理再也不须要的行版本,及时回收空间,这也增长了一些开销   2 INNODB支持的事务隔离等级   INNODB支持并实现了ISO标准的4个事务隔离等级,即 READ-UNCOMMITTED, READ-COMMITTED, REPEATABLE-READ, SERIALIZABLE.   1) READ UNCOMMITTED (能够读未提交的): 查询能够读取到其余事务正在修改的数据,即便其余事务的修改尚未提交.这种隔离等级没法避免脏读.   2) READ COMMITTED(只能够读已经提交的):其余事务对数据库的修改,只要已经提交,其修改的结果就是可见的,与这两个事务开始的前后顺序无关.这种隔离等级避免了脏读,可是没法实现可重复读,甚至有可能产生幻读.   3) REPEATABLE READ(可重复读):比read committed更进了一步,它只能读取在它开始以前已经提交的事务对数据库的修改,在它开始之后,全部其余事务对数据库的修改对它来讲均不可见.从而实现了可重复读,可是仍有可能幻读   4) SERIALIZABLE(可串行化):这是事务隔离等级的最高级别.其实现原理就是对于全部的query,即便是查询,也会加上读锁,避免其余事务对数据的修改.因此它成功的避免了幻读.可是代价是,数据库系统的并发处理能力大大下降,因此它不会被用到生产系统中.   咱们对MVCC和标准事务隔离等级有所了解之后,再结合实例来看看其具体表现吧.  

相关文章
相关标签/搜索