innerdb多版本并发控制之MVCC

       事务的并发控制有三种方案:悲观锁,乐观锁以及多版本并发控制。多版本并发控制能够与前面两种结合,从而提升数据库的读性能。mysql

       前面二者都是经过延迟或者终止相应的事务来解决事务之间的竞争条件来保证事务的串行执行。可是在实际场景中,事务大多数都是只读的,读请求是写请求的不少倍。若是读写之间没有并发控制机制,最坏的状况就是读请求和读到了已经写入的数据,这对不少应用是能够接受的。sql

       MVCC的全称就是多版本并发控制。它保存了已经更改的旧版本信息,以支持并发和回滚等事务功能。这项技术使得InnoDB的事务隔离级别下执行一致性读操做有了保证。换言之,为了查询在一些正在被另一个事务更新的行,而且能够看到它们被更新以前的值。这是一个能够用来加强并发性的强大技术,由于这样一来的话查询就不用等待另外一个事务释放锁。这项技术在数据库领域并非广泛使用的。数据库

      每一次写操做都会建立一个新版本的数据,每个版本的数据行都有一个惟一的时间戳。读操做会从有限个多版本的记录中找到最合适的结果直接返回,就是时间戳的最大值。更新操做就有些复杂了, 事务会先读取最新版本的数据计算出更新后的结果,而后建立一个新版本的数据,新数据的时间戳是目前数据行最大版本+1。数据版本的删除也是根据时间戳来选择的。MySql会将版本最低的数据定时删除以保证不会出现大量的历史记录。 这时候读写操做之间的冲突就不须要被关注。       并发

       MVVC最大的好处是:读不加锁,读写不冲突。在读多写少的应用中,读写不冲突很是重要,极大的增长了系统的并发性。利用MVCC实现了一致性非锁定读,保证了在同一个事务中屡次读取相同的数据返回的结果是同样的,解决了不可重复读问题。性能

       因此在mysql的repeatable read级别下也不会出现不可能重复读问题,而且经过Next-Key Lock解决了幻读问题。  事务

       InnoDB使用的是行锁,而且采用了多版本并发控制来提升读操做的性能。table

       什么是多版本并发控制呢?date

      其实就是在每一行记录的后面增长了三个隐藏列,记录建立版本号和删除版本号。而每个事务开启的时候,都会有惟一的递增版本号,被操做的数据会生成一条新的数据行(临时),可是在提交前对其余事务是不可见的,对于数据的更新(包括增删改)操做成功,会将这个版本号更新到数据的行中,事务提交成功,将新的版本号更新到此数据行中。这样保证了每一个事务操做的数据,都是互不影响,也不存在锁的问题。select

     MVVC下的CRUD请求

  select 

     当隔离级别是REPEATABLE READ时select操做,InnoDB必须每行数据来保证它符合两个条件:

     1.InnoDB必须找到一个行的版本,它至少要和事务的版本同样老(也即他的版本号不大于事务的版本号)。这保证了无论是事务开始以前,或者事务建立时,或者修改了这行数据的时候,这行数据是存在的。

    2.这行数据的删除版本必须是未定义或者比事务版本大。这样能够保证在事务开始以前这行数据没有被删除。

 insert

      InnoDB为这个新行记录当前的系统版本号。

 delete

     InnoDB将当前的系统版本号更新到这一行的删除id

 update

      InnoDB会写一个这行数据的新拷贝,这个拷贝的版本为当前的系统版本号。同时也会将这个版本号写到旧行的删除版本号里。

      这种额外的记录所带来的结果就是对于大多数查询而言根本不须要得到一个锁。他们只是简单的以最快的速度读取数据,确保只选择符合条件的行。这个方案的缺点在于存储引擎必须为每一行存储更多的数据,作更多的检查工做,处理更多善后操做。

      MVVC只工做在REPEATABLE READ和READ COMMITED隔离级别下。READ UNCOMMITED不是MVVC兼容的,由于查询不能找到适合他们事务版本的行版本,它们每次只能读到最新的版本。Serablable也不与MVVC兼容,由于读操做会锁定他们返回的每一行数据。

相关文章
相关标签/搜索