MVCC的全称就是多版本并发控制。这项技术使得InnoDB的事务隔离级别下执行一致性读操作有了保证。换言之,为了查询在一些正在被另外一个事务更新的行,并且可以看到它们被更新之前的值。这是一个可以用来增强并发性的强大技术,因为这样一来的话查询就不用等待另一个事务释放锁。这项技术在数据库领域并不是普遍使用的。
MVVC最大的好处是:读不加锁,读写不冲突。在读多写少的应用中,读写不冲突非常重要,极大的增加了系统的并发性。
InnoDB使用的是行锁,并且采用了多版本并发控制来提高读操作的性能。
什么是多版本并发控制呢?
其实就是在每一行记录的后面增加了两个隐藏列,记录创建版本号和删除版本号。而每一个事务开启的时候,都会有唯一的递增版本号,被操作的数据会生成一条新的数据行(临时),但是在提交前对其他事务是不可见的,对于数据的更新(包括增删改)操作成功,会将这个版本号更新到数据的行中,事务提交成功,将新的版本号更新到此数据行中。这样保证了每个事务操作的数据,都是互不影响,也不存在锁的问题。
MVVC下的CRUD
select
当隔离级别是REPEATABLE READ时select操作,InnoDB必须每行数据来保证它符合两个条件:
1.InnoDB必须找到一个行的版本,它至少要和事务的版本一样老(也即他的版本号不大于事务的版本号)。这保证了不管是事务开始之前,或者事务创建时,或者修改了这行数据的时候,这行数据是存在的。
2.这行数据的删除版本必须是未定义或者比事务版本大。这样可以保证在事务开始之前这行数据没有被删除。
inser
InnoDB为这个新行记录当前的系统版本号。
delete
InnoDB将当前的系统版本号更新到这一行的删除id
update
InnoDB会写一个这行数据的新拷贝,这个拷贝的版本为当前的系统版本号。同时也会将这个版本号写到旧行的删除版本号里。
这种额外的记录所带来的结果就是对于大多数查询而言根本不需要获得一个锁。他们只是简单的以最快的速度读取数据,确保只选择符合条件的行。这个方案的缺点在于存储引擎必须为每一行存储更多的数据,做更多的检查工作,处理更多善后操作。
MVVC只工作在REPEATABLE READ和READ COMMITED隔离级别下。READ UNCOMMITED不是MVVC兼容的,因为查询不能找到适合他们事务版本的行版本,它们每次只能读到最新的版本。Serablable也不与MVVC兼容,因为读操作会锁定他们返回的每一行数据。