作为第一篇对 MVCC 的学习材料,以下内容翻译自 Wikipedia。

1. 什么是MVCC

1.1 基础概念

MVCC,Multi-Version Concurrency Control,多版本并发控制。MVCC 是一种并发控制的方法,一般在数据库管理系统中,实现对数据库的并发访问;在编程语言中实现事务内存。

如果有人从数据库中读数据的同时,有另外的人写入数据,有可能读数据的人会看到『半写』或者不一致的数据。有很多种方法来解决这个问题,叫做并发控制方法。最简单的方法,通过加锁,让所有的读者等待写者工作完成,但是这样效率会很差。MVCC 使用了一种不同的手段,每个连接到数据库的读者,在某个瞬间看到的是数据库的一个快照,写者写操作造成的变化在写操作完成之前(或者数据库事务提交之前)对于其他的读者来说是不可见的。

当一个 MVCC 数据库需要更一个一条数据记录的时候,它不会直接用新数据覆盖旧数据,而是将旧数据标记为过时(obsolete)并在别处增加新版本的数据。这样就会有存储多个版本的数据,但是只有一个是最新的。这种方式允许读者读取在他读之前已经存在的数据,即使这些在读的过程中半路被别人修改、删除了,也对先前正在读的用户没有影响。这种多版本的方式避免了填充删除操作在内存和磁盘存储结构造成的空洞的开销,但是需要系统周期性整理(sweep through)以真实删除老的、过时的数据。对于面向文档的数据库(Document-oriented database,也即半结构化数据库)来说,这种方式允许系统将整个文档写到磁盘的一块连续区域上,当需要更新的时候,直接重写一个版本,而不是对文档的某些比特位、分片切除,或者维护一个链式的、非连续的数据库结构。

MVCC 提供了时点(point in time)一致性视图。MVCC 并发控制下的读事务一般使用时间戳或者事务 ID去标记当前读的数据库的状态(版本),读取这个版本的数据。读、写事务相互隔离,不需要加锁。读写并存的时候,写操作会根据目前数据库的状态,创建一个新版本,并发的读则依旧访问旧版本的数据。

一句话讲,MVCC就是用 同一份数据临时保留多版本的方式 的方式,实现并发控制。

这里留意到 MVCC 关键的两个点:

  1. 在读写并发的过程中如何实现多版本;
  2. 在读写并发之后,如何实现旧版本的删除(毕竟很多时候只需要一份最新版的数据就够了);

1.2 实现

MVCC 使用时间戳(TS)、递增的事务 ID(T)实现事务一致性。

MVCC 通过维护多版本数据,保证一个读事务永远不会被阻塞。对象 P 维护有多个版本,每个版本会有一个读时间戳(Read TimeStamp, RTS)和 写时间戳(Write TimeStamp, WTS),事务 Ti 读对象 P 的最新版本,该版本早于事务 Ti 的读时间戳 RTS(Ti)。

事务 Ti 要对 P 执行写操作,如果有其他事务 Tk 同时对 P 操作,则 RTS(Ti)必须要早于 RTS(Tk),即有 RTS(Ti) < RTS(Tk),这样对 Ti 对 P 的写操作才能完成。一般地,如果其他事务拥有 P 的一个更早的读时间戳的情况下,写操作是不能完成的。打个比方就是在存储前面有一道线,只有等你前面的人的完成了他们的事务,你的修改事务才可以提交完成。

重复说一下:每个对象 P 有一个时间戳 TS,如果事务 Ti 想要对 P 执行写操作,(写要先读)事务的读时间戳是 RTS(Ti),如果有其他事务拥有一个比较早的时间戳,有 TS(P) < RTS(Ti),这时事务 Ti 会退出并重新开始。否则,事务 Ti 创建一个 P 的新版本,并设置新版本 P 的时间戳,似的 TS = TS(Ti)。

MVCC 系统明显的缺点是会存储多个版本数据的冗余开销。但同时,读操作永不会被阻塞,这对那些以读操作为主的数据库来说非常重要。MVCC 实现了真的快照隔离(snapshot isolation),然后其他的并发控制方法要么是不完整的快照隔离方式,要么需要较高的性能损耗。

Wikipedia 中的内容有点繁琐,简单地,上面的描述,阐明了在同一数据版本下写操作的限制,已经通过多版本实现快照隔离的优越性。

1.3 示例

Time Object1 Object2
0 "Foo" by T0 "Bar" by T0
1 "Hello" by T1

Time=1的时候数据库的状态如上:

T0 写 Object1 为 "Foo",写 Object2 为 "Bar";之后 T1 写 Object1 为 "Hello",保留 Object2 为原始值。 Object1 的新值将取代 Time=0 时刻的旧值,并提供给 T1提交之后的发生的所有事务。Object1的版本号为0的旧数据会被 GC 掉。

如果有一个长事务 T2,在 T1之后对 Object1和 Object2 进行读操作,同时并行地,有事务 T3 做更新:删除 Object2、增加 Object3="Foo-Bar",在 Time=2 数据的状态如下所示:

Time Object1 Object2 Object3
0 "Foo" by T0 "Bar" by T0
1 "Hello" by T1
2 (delete)by T3 "Foo-Bar" by T3

Time=2 Object2有一个新版本:标记删除,同时增加了新对象 Object3 。T2 和 T3 并发执行,T2 看到的是数据在 Time=2 且 T3提交前的版本,这样 T2读到了 Object2="Bar""Object1="Hello"

以上就是 MVCC 在不加锁的情况下实现的快照隔离的读的原理。

1.4 历史

最早于1978年,论文『Naming and Synchronization in a Decentralized Computer System』清晰地介绍了 MVCC,这是公认关于 MVCC 最早的工作。

在1981年,论文『Concurrency Control in Distributed Database System』介绍MVCC的一些细节。

目前支持 MVCC 的数据库,包括 DB2、Oracle、Sybase、SQL Server、MySQL、PG 等所有主流数据库,以及 HBase、Couchbase、Berkeley DB 等 NoSQL 数据库

参考

  1. Wikipedia: Multiversion concurrency control
  2. List of databases using MVCC

关于 MVCC 的基础的更多相关文章

  1. 关于 MVCC 的基础【转】

    1. 什么是MVCC 1.1 基础概念 MVCC,Multi-Version Concurrency Control,多版本并发控制.MVCC 是一种并发控制的方法,一般在数据库管理系统中,实现对数据 ...

  2. lightning mdb 源代码分析(4)—MVCC/COW

    本博文将描述MVCC和cow技术以及LMDB中如何使用以及实现这两种技术. COW(Copy On Write): COW技术背后的思想是拖延技术,基本方法是假如有多个调用者需要访问的资源,在其初始化 ...

  3. MySQL数据库InnoDB存储引擎多版本控制(MVCC)实现原理分析

    文/何登成 导读:   来自网易研究院的MySQL内核技术研究人何登成,把MySQL数据库InnoDB存储引擎的多版本控制(简称:MVCC)实现原理,做了深入的研究与详细的文字图表分析,方便大家理解I ...

  4. MySQL数据库事务各隔离级别加锁情况--read committed && MVCC

    之前已经转载过几篇相关的文章,此次基于mysql 5.7 版本,从测试和源码角度解释一下RR,RC级别为什么看到的数据不一样 先补充一下基础知识 基本知识 假设对于多版本(MVCC)的基础知识,有所了 ...

  5. InnoDB多版本(MVCC)实现简要分析(转载)

    http://hedengcheng.com/?p=148 基本知识 假设对于多版本(MVCC)的基础知识,有所了解.InnoDB为了实现多版本的一致读,采用的是基于回滚段的协议. 行结构 InnoD ...

  6. innodb mvcc多版本实现

    出自:http://hedengcheng.com/?p=148 基本知识 假设对于多版本(MVCC)的基础知识,有所了解.InnoDB为了实现多版本的一致读,采用的是基于回滚段的协议. 行结构 In ...

  7. 转:InnoDB多版本(MVCC)实现简要分析

    InnoDB多版本(MVCC)实现简要分析 基本知识 假设对于多版本(MVCC)的基础知识,有所了解.InnoDB为了实现多版本的一致读,采用的是基于回滚段的协议. 行结构 InnoDB表数据的组织方 ...

  8. InnoDB多版本(MVCC)实现简要分析

    转载自:http://hedengcheng.com/?p=148 基本知识 假设对于多版本(MVCC)的基础知识,有所了解.InnoDB为了实现多版本的一致读,采用的是基于回滚段的协议. 行结构 I ...

  9. LMDB中的mmap、Copy On Write、MVCC深入理解——讲得非常好,常来看看!

    LMDB基本架构 lmdb的基本架构如下:  lmdb的基本做法是使用mmap文件映射,不管这个文件存储实在内存上还是在持久存储上.lmdb的所有读取操作都是通过mmap将要访问的文件只读的映射到虚拟 ...

随机推荐

  1. JavaScript之包装对象

    JavaScript对象是一种复合值:它是属性和已命名值的集合.通过"."符号来引用属性值.当属性值是一个函数时,称为方法. ①一段你常用但却未必明白其真正底层原理的代码: var ...

  2. async和await关键字实现异步编程

    async和await关键字实现异步编程 异步编程   概念 异步编程核心为异步操作,该操作一旦启动将在一段时间内完成.所谓异步,关键是实现了两点:(1)正在执行的此操作,不会阻塞原来的线程(2)一旦 ...

  3. JQuery之初探

    软考过后又进入了紧张的B/S学习阶段,因为自己的进度比較慢,所以更要加进学习.如今就来总结下JQuery的一些基础知识: JQuery定义 jQuery是一套跨浏览器的JavaScript库,简化HT ...

  4. 设置韩澳大利亚sinox弄winxp清除字体和界面美观

    澳大利亚开始与汉sinox一直以为接口暗淡,字体比较模糊,否winxp光明,导致眼比较辛苦的眼睛.比方说,可能不那么黯淡刺眼,有益眼睛,但我不能忍受字体模糊.即使调整分辨率,,但是字体模糊还是没有改观 ...

  5. 写手Remoting测试工具

    基于.NET开发分布式系统.经经常使用到Remoting技术.在測试驱动开发流行的今天.假设针对分布式系统中的每一个Remoting接口的每一个方法都要写具体的測试脚本,无疑很浪费时间.所以,我想写一 ...

  6. 从头开始学JavaScript (七)——函数

    原文:从头开始学JavaScript (七)--函数 一.return 函数在执行完return之后停止并立即退出. return返回值:与return: 如下两个例子: function sum(n ...

  7. C语言第11课

    主要内容:函数指针 一.函数指针定义 int  maxValue(int  a,int  b) { return   a > b ? a : b; } 函数名和数组名一样是地址,存在在代码区 i ...

  8. vs2012 + web api + OData + EF + MYsql

    vs2012 + web api + OData + EF + MYsql 开发及部署 先说下我的情况,b/s开发这块已经很久没有搞了,什么web api .MVC.OData都只是听过,没有实际开发 ...

  9. cfs

    转自:http://www.cnblogs.com/openix/p/3254394.html 下文中对于红黑树或链表组织的就绪队列,统称为用队列组织的就绪队列.                    ...

  10. jAVA 得到Map价值

    jAVA 获取Map中的值 Map<String, String> map=new HashMap<String, String>(); map.put("name& ...