MySQL的多版本并发控制之什么是MVCC?InnoDB的MVCC实现
vcc">什么是MVCC
MySQL的默认隔离级别REPEATABLE READ(可重复读)解决了脏读,不可重复读问题,但还是无法解决幻读的问题。所谓幻读,指的是A事务读取某个范围内的记录时,另外一个B事务又在该范围内插入了新的记录,A事务再次读取该范围的记录时,会产生幻行。
InnoDB和XtraDB存储引擎通过多版本并发控制(Multiversion Concurrency Control)MVCC解决了幻读的问题。
不仅是MySQL,包括Oracle,PostgreSQL等数据库系统也都实现了MVCC。
MVCC并没有正式的规范,也没有一个统一的实现标准。不同的数据库实现的机制不尽相同,不同的存储引擎的MVCC实现也不同,虽然实现机制有所不同,但大都实现了非阻塞的读操作,写操作也只是锁定必要的行。典型的有乐观并发控制和悲观并发控制。
下面通过InnoDB存储引擎来看下MVCC是如何工作的。
InnoDB的MVCC实现
InnoDB的MVCC,是通过在每行记录后面保存两个隐藏的列来实现的。这两个列,一个保存了行的创建时间,一个保存行的过期时间。该时间并不是实际的系统时间值,而是系统版本号(system version number)。每开始一个新的事务,系统版本号都会自动递增,这是MySQL服务器的机制。
事务开始时刻的系统版本号会作为该事务的版本号,用来和查询到的每行记录的版本号进行比较。
InnoDB在默认隔离级别REPEATABLE READ(可重复读)下,MVCC具体操作如下:
SELECT
a.只查找创建时间版本早于当前事务版本的数据行,这样确保查询出来的行,要么是在事务开始前已经存在的,要么是事务这身插入或者修改过的。 b.行的删除时间版本号要么未定义,要么大于当前事务版本号。这样可以确保事务读取到的行,在事务开始之前未被删除。
INSERT
InnoDB为新插入的每一行保存当前系统版本号作为创建版本号。
DELETE
InnoDB为删除的每一行保存当前系统版本号作为删除版本号。
UPDATE
InnoDB为更新的每一行保存当前系统版本号到原来的创建版本号,同时保存当前系统版本号到原来的行作为行删除版本号。
MVCC的优缺点
优点:保存这两个额外系统版本号,使大多数读操作都可以不用加锁。这样设计使得读操作简单,性能更好,并且保证读到的数据是符合标准的行。
缺点:每行记录都需要额外的存储空间,需要做更多的行检查工作,更多额外的维护工作。
注意点
MySQL的MVCC只在REPEATABLE READ(可重复读)和READ COMMITTED(提交读)这两个隔离级别下工作。另外两个隔离级别和MVCC不兼容,READ UNCOMMITTED(未提交读)总是读取最新的数据行,SERIALIZABLE(可串行化)则会对所有读取的行都加锁。
上一篇: 数据结构--递归学习