阅读 663

mongoDB wiredTiger存储引擎学习总结

1.wiredTiger

存储引擎主要负责管理数据如何存储在硬盘和内存上。

1) mongoDB存储引擎查看

mongoDB3.2版本之后选择了wiredTiger作为默认存储引擎,查看数据库存储引擎语句如下:

db.serverStatus()
复制代码

2)原理解析

wiredTiger通过Btree管理数据,B树的数据结构如下图。

1.MongoDB本身不支持事务实现,但是wiredTiger存储引擎可以通过事务快照和并发控制技术实现事务及ACID。

2.Wiredtiger采用Copy on write的方式管理修改操作(insert、update、delete),修改操作会先缓存在cache里,持久化时,修改操作不会在原来的leaf page上进行,而是写入新分配的page,每次checkpoint都会产生一个新的root page。
Checkpoint时,wiredtiger需要将btree修改过的PAGE都进行持久化存储

3.大部分数据库采用的都是硬盘级索引,即MongoDB中每个Btree节点为一个page单位,其中在数据查找的过程中,Btree结点上的数据需要以page为单位从硬盘中加载到内存中,或者从内存中写入硬盘
4.mongoDB是文档级数据存储,数据存储结构简单,一般使用的需求都是IO次数少

对于mysql来说,B+树的根节点和支结点不用存储数据区域

1.B+树的存储结构是这样的,每个节点保存的是关键字和指向下一个节点的指针; 2.和b tree 两个明显的区别就是,第一个是非叶子节点不保存数据区域,第二点是有左闭合区间,讲一下数据规则;

聊一下MongoDB和mysql的对比 1.Mysql关系型数据库—需要范围查询 MongoDB 文档级别 不需要范围查询

2.mongoDB一般在设计的时候都是尽可能的减少磁盘与硬盘之间的IO来提高性能;而Btree刚好是数据与关键字存放在同一个结点,所以mongoDB使用btree

3)为什么mysql使用B+ tree 而MongoDB用b tree;

1.首先是这样每个结点保存的关键字个数更多

2.每个结点加载到内存中,如果不是叶子节点,就不用进行扫库操作,如果是b树,每次读写到内存的时候都需要扫库;

3.B+ tree的叶子节点是以链表的时候把每个点连在一起,他们存储是有序的,可以使用范围查询

4.mongoDB一般在设计的时候都是尽可能的减少磁盘与硬盘之间的IO来提高性能;而Btree刚好是数据与关键字存放在同一个结点,所以mongoDB使用btree


2.wiredTiger事务实现

MongoDB不仅能将数据持久化存储到硬盘文件中,而且还能将数据只保存到内存中;

然后不同的存储引擎的区别就是使用了不同的存储机制,锁定技术,或者是索引技术等等;然后他们的性能也不一样, WT实现事务需要用到这三个关键的技术

Snapshot,MVCC Redo log;

定义了一个事务的整体全局对象wt_transaction,里面包括id MVCC 多版本并发控制,基于keyvalue的value值的链表,主要是在链表里存储事务id 和本次事务下操作所修改的值。

下面分别介绍这几个技术看看他们是如何实现事务的:

1)Snapshot

WT 引擎中的 snapshot_oject 是有一个最小执行事务 snap_min、一个最大事务 snap max 和一个处于 [snap_min, snap_max] 区间之中所有正在执行的写事务序列组成。如果上图在 T6 时刻对系统中的事务做一次 snapshot,那么产生的T6 能访问的事务修改有两个区间:所有小于 T1 事务的修改 [0, T1) 和 [snap_min, snap_max]  区间已经提交的事务 T2 的修改。换句话说,凡是出现在 snap_array 中或者事务 ID 大于 snap_max 的事务的修改对事务 T6 是不可见的。如果 T1 在建立 snapshot 之后提交了,T6 也是不能访问到 T1 的修改。这个就是 snapshot 方式隔离的基本原理。

2)MVCC

问题 什么是并发控制方法?

如果有人从数据库中读数据,有另外的人写入数据,有可能读数据的人看到的数据是不完整的,不同数据库提出了很多方法来解决这个问题,解决这个问题的方法叫并发控制方法

解决:mysql数据库中对这个问题的解决方案是加锁,通过加锁,让所有读的用户都等写用户工作完成,这个效率会比较差; 而mongoDB中使用的MVCC:使用的是不同的并发控制方法

每次有写操作之后,把修改后的内容以wt_mvcc的数据格式添加到红色箭头这个头部;然后读操作每次都是从链表头根据对应的修改事务ID和本次读操作的snapshot结合判断是否可以读,如果不可读,则往MVCC list尾方向移动,直到找到能读的数据版本;

WT 中的数据修改都是在这个链表中进行 append 操作,每次对值做修改都是 append 到链表头上,每次读取值的时候读是从链表头根据值对应的修改事务 transaction_id 和本次读事务的 snapshot 来判断是否可读,如果不可读,向链表尾方向移动,直到找到读事务能都的数据版本。样例如下:上图中,事务 T0 发生的时刻最早,T5 发生的时刻最晚。T1/T2/T4 是对记录做了修改。那么在 MVCC list 当中就会增加 3 个版本的数据,分别是 11/12/14。如果事务都是基于 snapshot 级别的隔离,T0 只能看到 T0 之前提交的值 10,读事务 T3 访问记录时它能看到的值是 11,T5 读事务在访问记录时,由于 T4 未提交,它也只能看到 11 这个版本的值。这就是 WT 的 MVCC 基本原理。

3)Redo log

每60s或log文件达到2GB时会做一次Checkpoint,将当前的数据持久化,产生一个新的快照。

4)事务实现

一般:

1.创建事务对象;开启对象

2.执行,执行如果遇到冲突或执行失败,需要回滚事务

3.如果执行都正常完成,只需要提交即可;

而Wiredtiger存储引擎在事务开启的过程中,在创建事务对象的同时回把这个对象加入到全局事务管理器中; 事务在执行的时候,如果是读操作,就不做任何操作,因为读操作不需要rollback和commit;具体过程如下图

参考:

mp.weixin.qq.com/s?__biz=MzA…

www.mongoing.com/archives/25…

关注下面的标签,发现更多相似文章
评论