MVCC提供了数据库并发访问功能。数据库利用MVCC保证每个数据库Connection都拥有一份独立的快照(Snapshot),并利用这份快照进行CRUD。一个Connection操作(CRUD)的结果,只要该Connection的事务不提交,这些结果其他Connection是看不到的。
锁的粒度
提高并发性的手段之一就是细化锁的力度,也就是只对你想要修改的数据加锁。只要修改彼此不冲突,通过减少被锁住的数据,就能尽可能的多修改数据。Mysql的不同的存储引擎使用的锁力度也不同,MYISAM使用了表(Table) 锁,而Innodb跟Oracle一样使用的是行锁。但基于锁的并发控制要求应用程序进行获得锁、检查锁是否可用,释放锁等操作,这些操作都会影响应用程序的性能。
使用MVCC多版本并发控制比锁定模型的主要优点是在MVCC里, 对检索(读)数据的锁要求与写数据的锁要求不冲突, 所以读不会阻塞写,而写也从不阻塞读。恰当地使用 MVCC 总会比锁有更好地性能。
在一个MVCC系统中,每一行有包含了2个额外的字段——创建版本号和删除版本号。这2个字段表示这一行数据室什么时候创建的以及什么时候过期(也就是删除)。当发生了某个事件,数据库就会生成一个版本号并保存起来。版本号是一个数字,每次查询数据库的时候就递增。数据库负责记录运行的查询以及相关联的版本号。接下来我们看看MVCC系统是怎么工作地。
- SELECT语句
- 当需要从表中检索数据的时候,服务器要确保只有满足以下条件的记录才能做为查询结果返回:
-
-
记录行的创建ID必须小于等于系统版本号。这样才能保证这行数据是在当前查询开始前就已经生成了的。
-
如果记录行的删除ID不为空,那么删除ID就要大于当前系统的版本号。 这样才能确保这行数据在查询开始以前未被删除。
-
行记录的创建ID不再运行中的查询列表中。这样保证这行数据不是由正在运行的查询生成或修改得到的。
- INSERT语句
- 当需要在某这表加入一行数据的时候,数据库就把当前系统的版本号作为该行数据的创建ID和这行数据一并加入到表中。
- DELETE语句
-
删除某行记录的时候,数据库就把系统的当前版本号做为该行数据的删除ID。
- UPDATE 语句
-
当某行数据需要修改的时候,数据库就创建该行数据的拷贝并用系统当前版本号做为新纪录的创建ID。 同时用这个版本号做为老数据的删除ID。
用以上的实现方式保证了读操作是永远不会锁住表、页和记录行。
总结
以上内容是MVCC这块学习内容的整理,由于没有read过实际MVCC的数据库的代码,感觉还是有很多不明确的地方,纸上得来终觉浅呀!
参考资料
MVCC介绍
Multiversion concurrency control
High Performance MySQL第一版 第2.2 节