该章节我准备和第五章一起记录,第五章节主要写的是Mysql各个引擎的特点和介绍。
之所以要写到一起,也还有另一个原因,那就是第五章介绍到了 InnoDB 引擎的时候带给了我一些疑惑。
还是先说这一章的多版本并发控制。
多版本并发控制
多版本并发控制(MVCC)。 Innodb 的行锁,并不只是简单使用行锁机制,而是行锁配合多版本并发控制技术实现的行锁。
多版本并发控制并不是一个系统,而是一种类似于设计模式思想的东西,所以每个存储引擎对于实现MVCC的方式都不同。
它的优点:很好的解决了幻读问题。避免了很多情况下的加锁操作。
以下是重点原文:
InnoDB 通过为每个数据行增加两个隐含值的方式来实现 MVCC 。这两个隐含值记录了行的创建时间,以及它的过期时间(或者叫删除时间)。
每一行都存储了事件发生时的系统版本号(我觉得叫做数据版本号更好理解),用来替代事件发生时的实际时间。
每一次,开始一个新事务时,版本号都会自动递增。每个事务都会保存它在开始时的"当前系统版本的记录",而每个查询都会根据事务的版本号,检查每行数据的版本号。
如何简单的理解多版本并发控制(我自己的理解)?即你开启一个事务,版本号就会递增一个,假设当前事务的数据片的版本号为 25 ,那么,该事务中所做的数据片操作应该就是小于当前版本号中最大的版本号数据,即读到的数据为最贴近小于当前号版本的数据。
也就是说每一条数据都会有自己的版本号。在同一个事务中都只会对那个版本的数据进行处理,就解决了幻读问题。
MVCC 减少了锁的开销,同时相对应的增加了额外数据保证版本号,要对版本号做检查和整理。拥有 MVCC 支持的行级加锁并发性能最高,同时开销也是最高的。
第五章的 InnoDB 带来的疑惑
以下是第五章的原文:
InnoDB使用MVCC机制获取高并发性能,并且实现所有四个标准隔离级。它的默认隔离级为 PEPEATABLE READ(Pepeatable read),在这个隔离级上,它使用了间隙锁(Next-key locking)策略防止 "幻读产生":不仅对查询中读取的行进行加锁,而且还对索引结构中的间隙(Gaps)进行加锁,以防幻影插入。
看到这里的时候,我就有点疑惑了,我记得这本书前面是写的 MVCC 解决的幻读问题啊。于是我往前翻,终于找到了这么一句话,以下是原文。
InnoDB 和 Falcon 存储引擎通过多版本并发控制机制解决了幻读问题。
那么到底是谁解决了幻读问题呢?
为此我去搜索引擎上去看了一些人对于这个问题的看法。我觉得都有些牵强。从第一大章节来仔细看的话,我觉得书中描述是没错的。
MVCC 多版本并发控制机制解决了幻读问题,这没错,间隙锁策略防止"幻读"问题的产生。也没错。实际上,这两句话描述的是两个事情!
多版本并发控制解决的是在同一个事务中的两次范围读取保证一致(因为保证了数据版本号一致,所以不用去管其他事务是否对该数据片进行了增删,因为一旦增删则会产生新的版本号,而当前进行查询的事务中始终会使用同一版本号的数据)!
间隙锁,解决的是我保证让你不会出现幻读情况!即你在事务期间,我给这个数据片的所有间隙,空隙,加上锁,甚至连索引都加上锁。让你没有机会产生幻读问题。
所以我认为还是 MVCC 解决了幻读问题。读了几篇别人的博客,谈到了间隙锁,发现间隙锁还会出现一些其他有趣的问题,在本篇中就不再阐述,等我看到间隙锁这一章节的时候,再来重开一篇记录。
原文链接: 高性能 Mysql 第一章第四节 多版本并发控制