MVCC背景:
MySQL事务默认使用REPEATABLE READ(可重复读)隔离级别。该隔离级别还是会产生幻读问题。即当某个事务读取某个范围的记录时,另外一个事物在该范围插入了新的记录,那么之前的事务再次读取该范围的记录时,会产生幻行。MySQL InnoDB就是通过多版本并发控制(MVCC)解决幻读问题。
MVCC简介:
MVCC将数据库的行锁与行的多个版本结合起来,只需要很小的开销,就可以实现非锁定读,从而大大提高数据库系统的并发性能.
MVCC实现原理:
MVCC保存某个时间点上的数据快照。一个事务内,看到的是同一个版本的快照,数据一致。不同事务在同一时间点看到的数据会不一致,因为他们得到的数据版本不一样。InnoDB在每行记录存在额外的隐藏字段,其中一列存储行被更新的版本号,另外一列存储行被删除的版本号。每当一个事务开始的时候,innodb都会给这个事务分配一个递增的版本号,所以版本号也可以被认为是事务号.对于每一个”查询”语句,innodb都会把这个查询语句的版本号同这个查询语句遇到的行的版本号进行对比,然后结合不同的事务隔离等级,来决定是否返回该行。当隔离级别是REPEATABLE
READ时,这种策略下,select、delete、 insert、 update语句如何操作:
1) SELECT 对于select语句,只有同时满足了下面两个条件的行,才能被返回:
•行的被修改版本号小于或者等于该事务号
•行的被删除版本号要么没有被定义,要么大于事务的版本号:行的删除版本号如果没有被定义,说明该行没有被删除过;如果删除版本号大于当前事务的事务号,说明该行是被该事务后面启动的事务删除的,由于是repeatable read隔离等级,后开始的事务对数据的影响不应该被先开始的事务看见,所以该行应该被返回.
2) INSERT 对新插入的行,行的更新版本被修改为该事务的事务号
3) DELETE 对于删除,innodb直接把该行的被删除版本号设置为当前的事务号,相当于标记为删除,而不是实际删除
4) UPDATE 在更新行的时候,innodb会把原来的行复制一份到回滚段中,并把当前的事务号作为该行的更新版本
InnoDB存储引擎MVCC的实现策略:
在每一行数据中额外保存两个隐藏字段:当前行创建时的版本号和删除时的版本号(可能为空)。每个事务又有自己的版本号,这样事务内执行CRUD操作时,就通过版本号的比较来达到数据版本控制的目的。具体做法见下面的示意图。
MVCC缺点:
为了实现多版本,InnoDB需要维护额外的隐藏字段,以及清理不需要的行版本,带来额外开销。
更多相关教程请访问 MySQL视频教程