我理解的MVCC内部实现原理

  MySQL InnoDB存储引擎,实现的是基于多版本的并发控制协议——MVCC (Multi-Version Concurrency Control) (注:与MVCC相对的,是基于锁的并发控制,Lock-Based Concurrency Control)。MVCC最大的好处,相信也是耳熟能详:读不加锁,读写不冲突。在读多写少的OLTP应用中,读写不冲突是很是重要的,极大的增长了系统的并发性能,这也是为何现阶段,几乎全部的RDBMS,都支持了MVCC。并发

  

  对于delete操做,innodb是经过先将要删除的那一行标记为删除,而不是立刻清除这一行,由于innodb实现了MVCC,这些undo段用来实现MVCC多版本机制。锁不阻塞读,读也不阻塞写,这样大大提升了并发性。那么在一致性读的时候,怎么才能找到和事务开始的那个版本呢?性能

	主键索引,每一个行都有一个事务ID和一个undo ID,这个undo ID指向了这行的先前版本的位置。
	非主键索引(辅助索引secondary index),经过先找主键索引再找到undo段。而对于update操做,则是先标记删除,而后insert一个新的行,接下来若是有一致性读,那么查找old version的行的原理和delete操做是同样的

  

  innoDB的行记录格式中有6字节事务ID的和7字节的回滚指针,经过为每一行记录添加这两个额外的隐藏值来实现MVCC,这两个值一个记录这行数据什么时候被建立,另一个记录这行数据什么时候过时(或者被删除)。可是InnoDB并不存储这些事件发生时的实际时间,相反它只存储这些事件发生时的系统版本号。这是一个随着事务的建立而不断增加的数字。每一个事务在事务开始时会记录它本身的系统版本号。每一个查询必须去检查每行数据的版本号与事务的版本号是否相同。让咱们来看看当隔离级别是REPEATABLE READ时这种策略是如何应用到特定的操做的。指针

 * SELECT:
当隔离级别是REPEATABLE READ时select操做,InnoDB必须每行数据来保证它符合两个条件:
一、InnoDB必须找到一个行的版本,它至少要和事务的版本同样老(也即它的版本号不大于事务的版本号)。这保证了不论是事务开始以前,或者事务建立时,或者修改了这行数据的时候,这行数据是存在的。
二、这行数据的删除版本必须是未定义的或者比事务版本要大。这能够保证在事务开始以前这行数据没有被删除。
符合这两个条件的行可能会被看成查询结果而返回。
* INSERT:
InnoDB为这个新行记录当前的系统版本号。 * DELETE:
InnoDB将当前的系统版本号设置为这一行的删除ID。 * UPDATE:
InnoDB会写一个这行数据的新拷贝,这个拷贝的版本为当前的系统版本号。它同时也会将这个版本号写到旧行的删除版本里。 这种额外的记录所带来的结果就是对于大多数查询来讲根本就不须要得到一个锁。他们只是简单地以最快的速度来读取数据,确保只选择符合条件的行。这个方案的缺点在于存储引擎必须为每一行存储更多的数据,
作更多的检查工做,处理更多的善后操做。 MVCC只工做在REPEATABLE READ和READ COMMITED隔离级别下。READ UNCOMMITED不是MVCC兼容的,由于查询不能找到适合他们事务版本的行版本;它们每次都只能读到最新的版本。
SERIABLABLE也不与MVCC兼容,由于读操做会锁定他们返回的每一行数据。

  

并发控制技术:blog

LBCC:Lock-Based Concurrency Control,基于锁的并发控制。
MVCC:Multi-Version Concurrency Control,基于多版本的并发控制协议。纯粹基于锁的并发机制并发量低,MVCC是在基于锁的并发控制上的改进,主要是在读操做上提升了并发量。
在MVCC并发控制中,读操做能够分红两类:
1)快照读 (snapshot read):读取的是记录的可见版本 (有多是历史版本),不用加锁(共享读锁s锁也不加,因此不会阻塞其余事务的写)。
2)当前读 (current read):读取的是记录的最新版本,而且,当前读返回的记录,都会加上锁,保证其余事务不会再并发修改这条记录。
相关文章
相关标签/搜索