lightning mdb 源代码分析(4)—MVCC/COW
本博文将描述MVCC和cow技术以及LMDB中如何使用以及实现这两种技术。
COW(Copy On Write):
COW技术背后的思想是拖延技术,基本方法是假如有多个调用者需要访问的资源,在其初始化的时候是不能区分的,即对于多个调用者来说,这资源就是一样的。这样就可以给每个
调用者一个指向资源的指针即可。这种方法一直持续到调用者需要进行修改所需要访问的资源时,在这个时候,调用者将被分配到一份真正私有的资源拷贝,这样调用者对资源的任意
改动对于其它调用者来说都是不可见的。所有的以上操作对于调用者来说是透明的,这种方法最大的好处就是假如调用者不修改资源,私有拷贝就不会被创建。因此这种技术对于读大于
写的应用场景来说特别合适,比如说虚拟内存与分页、数据库、string对象等等,都使用此技术以提升系统性能。
MVCC(Multiversion concurrency control):
MVCC是数据库系统实现并发控制和一般系统中实现事务性内存控制的一种技术,主要用于并发控制,使用MVCC将读不会阻塞写,写不会阻塞读,只有两个线程写同一行数据可能导致冲突,
因此可以提供最高的并发性。MVCC对于并发写同一区域的数据可能导致冲突要求事务回滚或者互相等待资源导致死锁。
对于数据库系统来说,若一个用户正在读数据的同时,另一个用户正在写同一个数据,则读用户可能读到写到一半的数据或者不一致的数据,因此数据库系统都会使用并发控制。最简单的方式就是
写时阻塞所有读,这就是封锁技术。MVCC的方式是每个用户看到的数据是其连接上数据库时的快照,所有写操作对数据的改变其他数据库用户都不能看到,除非改变已经完成(即事务已提交)。
在MVCC中数据的更新使用delete(标记)+insert实现,因此对于同一行数据可能在数据库多个地方存在不同版本,旧数据和新数据不在同一个地方(不是就地更新),但只有最后一个版本是最新的,
之前的版本对于之前的事务有效。MVCC的好处是对于读数据来说,哪怕数据在整个事务过程中被别的用户修改删除,其读到的数据就是刚开始使用数据库时的那份数据。另外就是其不需要及时删除
旧数据,这样避免了系统来回换页导致性能下降。对于文档型数据库来说,还可以优化为数据存储在连续区块,delete+insert可以不更新里面部分数据,这样对于后续组装数据提供最大便利。MVCC
提供了即时的一致性视图,读写隔离,不需要进行封锁,因此可以提高并发性。
MVCC的图示:
图1:事务T1改变数据V1,将其改为数据V2,在堆中,数据如下图
图2:事务T3改变了V2,将其改为V3,在堆中,数据如下图:目前事务T2还在活动中,所以V1和V2属于recently dead状态,而不是真的dead状态。
图3:从可视性而言,事务T0只能看到数据V1。因为它早于事务T1启动。
图4:事务T1提交后,事务T2启动,此时事务T3尚未启动,故T2可以看到T1提交后的数据V2。
图5:事务T3提交后,事务T4启动,故T4只能看到数据V3。
图6: 前面说过,当还有事务活动中访问数据V1和V2,V1和V2的状态是recently dead。
当T0和T2都结束,已经没有事务在访问数据V1和V2了,此时V1和V2为dead状态,所以V1和V2都成为VACUUM的处理对象了。
以上几图以postgresql的MVCC实现为例描述了不同事务间读写操作过程以及其访问的数据。对于同时更新来说,主要多了
更新冲突检测,若更新存在读写依赖冲突则,更新失败,事务必须回滚,若存在互相依赖,则会解锁某一个事务,以避免死锁。
MVCC/COW在LMDB中的实现
LMDB对MVCC加了一个限制,即只允许一个写线程存在,从根源上避免了写写冲突,当然代价就是写入的并发性能下降。因为只有
一个写线程,所以不会不需要wal日志、读写依赖队列、锁队列等一系列控制并发、事务回滚、数据恢复的基础工具。MVCC的基础
就是COW,对于不同的用户来说,若其在整个操作过程中不进行任何的数据改变,其就使用同一份数据即可,若需要进行改变,比如
增加、删除、修改等,就需要在私有数据版本上进行,修改完成提交之后才给其他事务可见。
LMDB中,数据操作的基本单元是页,因此cow也是以页为单位,对应函数是mdb_page_touch,mdb_page_copy,copy真正实现页面复制,
touch调用copy完成复制,然后修改pgno后插入到B+Tree当中,这样对于此次事务,后续的操作访问的数据页就是最新的数据页面,而非
事务启动时对应的数据页面,且此页面与其他页面的关联关系仅在本事务页面列表中可见,对其他事务不可见。
实际上通过以上两个函数也实现了MVCC的核心,对于读写的控制,通过mdb_txn_begin控制,在其中,事务启动时会检查读写锁的情况,
若事务需要更新数据,则会被阻止,若只是读数据,则不管是否有写事务存在,读锁都可以获得。
MVCC的一个副作用就是对于存在大量写的应用,其数据版本很多,因此旧数据会占用大量空间,postgresql解决此问题通过vacuum命令,
LMDB中通过freedb解决,即将不再使用的旧的数据页面空间插入到一颗b-Tree当中,这样旧空间在所有事务不再访问之后就可以被LMDB
使用,从而避免了需要定期执行清理操作。当然其副作用是数据只能保持最新不能恢复到任意时刻,未执行vacuum之前,保存所有版本的数据库
可以恢复到任意时刻。
本文参考了如下资料,在此一并表示感谢。
https://en.wikipedia.org/wiki/Multiversion_concurrency_control
http://www.kuqin.com/system-analysis/20120319/319108.html
http://blog.chinaunix.net/uid-20726500-id-4040024.html
http://www.cnblogs.com/gaojian/p/3295951.html
lightning mdb 源代码分析(4)—MVCC/COW的更多相关文章
- lightning mdb 源代码分析(1)
lighting mdb(lmdb) 是一个高性能mmap kv数据库,基本介绍和文档参见symas官网,本文将尝试分析其源代码结构以理解数据库设计的关键技术. 本系列文章将尝试从以下几个方面进行分析 ...
- lightning mdb 源代码分析系列(3)
本系列前两章已经描述了系统架构以及系统构建的基础内存映射,本章将详细描述lmdb的核心,外存B+Tree的操作.本文将从基本原理.内存操作方式.外存操作方式以及LMDB中的相关函数等几方面描述LMDB ...
- lightning mdb 源代码分析(5)-事务控制
本博文系列前面已经探讨了LMDB的系统架构.MMAP映射.B-Tree操作等部分,本文将尝试描述LMDB中的事务控制的实现. 事务的基本特征: 事务是恢复和并发控制的基本单位.它是一个操作序列,这些操 ...
- lightning mdb 源代码分析(2)
本系列前一篇已经分析了lightningmdb的整体架构和主要的数据结构.本文将介绍一下MMAP原理以及lmdb中如何使用它. 1. Memory Map原理 内存映射文件与虚拟内存有些类似,通过内存 ...
- HBase源代码分析之HRegion上MemStore的flsuh流程(二)
继上篇<HBase源代码分析之HRegion上MemStore的flsuh流程(一)>之后.我们继续分析下HRegion上MemStore flush的核心方法internalFlushc ...
- android-plugmgr源代码分析
android-plugmgr是一个Android插件加载框架,它最大的特点就是对插件不需要进行任何约束.关于这个类库的介绍见作者博客,市面上也有一些插件加载框架,但是感觉没有这个好.在这篇文章中,我 ...
- Twitter Storm源代码分析之ZooKeeper中的目录结构
徐明明博客:Twitter Storm源代码分析之ZooKeeper中的目录结构 我们知道Twitter Storm的所有的状态信息都是保存在Zookeeper里面,nimbus通过在zookeepe ...
- 转:SDL2源代码分析
1:初始化(SDL_Init()) SDL简介 有关SDL的简介在<最简单的视音频播放示例7:SDL2播放RGB/YUV>以及<最简单的视音频播放示例9:SDL2播放PCM>中 ...
- 转:RTMPDump源代码分析
0: 主要函数调用分析 rtmpdump 是一个用来处理 RTMP 流媒体的开源工具包,支持 rtmp://, rtmpt://, rtmpe://, rtmpte://, and rtmps://. ...
随机推荐
- tcp/IP点对点通信程序
点对点的通信 服务器端与客户端在建立连接之后创建一个进程 服务器端: 子进程用于接收主机的输入并将数据发送出去.父进程用于接收客户端的数据并输出到主机. 子进程一直等待主机的输入,输入的数据放在发送缓 ...
- poj 1833
http://poj.org/problem?id=1833 next_permutation这个函数是用来全排列的,按字典的序进行排列,当排列无后继的最大值时,会执行字典升序排列,相当于排序: 当排 ...
- 【转】如何用 Chrome for Android 做远程遥控 debugging
http://blog.csdn.net/wuchengzhi82/article/details/22190435
- win10远程桌面连接
有的情况下,Win10设置了允许远程桌面连接后,远程主机仍然不能桌面连接到目标主机上,这时可以在目标主机上尝试如下修改: 开始-->运行->gpedit.msc->计算机配置-> ...
- poj 1625 (AC自动机好模版,大数好模版)
题目 给n个字母,构成长度为m的串,总共有n^m种.给p个字符串,问n^m种字符串中不包含(不是子串)这p个字符串的个数. 将p个不能包含的字符串建立AC自动机,每个结点用val值来标记以当前节点为后 ...
- Greedy:三角形问题
题目大意:有n根长度的为a1,a2....an的棒子,如果棒子可以组成三角形,求这些棒子能组成的三角形的最大周长? 这一题,一般人只能想到三重循环,当然我们是CS专业的,不能这样想,其实这题可以用DP ...
- codeforces A. Xenia and Divisors 解题报告
题目链接:http://codeforces.com/problemset/problem/342/A 题目意思:给出n个数,找出n/3个组且每组有3个数,这三个数必须要符合两个条件:1.a < ...
- Java 批量反编译class文件,并保持目录结构
jad -o -r -d d:\src -s java C:\Users\spring\Desktop\egorder3.0\WEB-INF\classes\**\*.class -o - overw ...
- Unix系统编程_cha11.6_线程同步
#include <stdio.h>#include <pthread.h>#include <stdlib.h> #define NHASH 29#define ...
- 手机/平板 连接局域网访问局域网电脑Web服务器进行移动端页面测试
1.开启本地服务器(我用的是XAMPP) 2.查看本机IP Mac:点击左上角的苹果标志,选择系统偏好设置,弹出系统偏好设置面板-----点击网络,选择高级,切换到tcp/ip 选项卡 会看到本机IP ...