前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >WiredTiger存储引擎之五:与事务相关的数据结构以及并发控制机制

WiredTiger存储引擎之五:与事务相关的数据结构以及并发控制机制

作者头像
MongoDB中文社区
发布2020-09-10 15:11:17
8540
发布2020-09-10 15:11:17
举报
文章被收录于专栏:MongoDB中文社区MongoDB中文社区

前言

WiredTiger存储引擎系列文章将从逻辑正确、内容完整的角度全面介绍WiredTiger存储引擎。本篇是WiredTiger存储引擎系列文章第5篇,前面篇章分别是:

WiredTiger存储引擎之一:基础数据结构分析

WiredTiger存储引擎之二:一个Page的生命周期

WiredTiger存储引擎之三:Checkpoint原理

WiredTiger存储引擎之四:WT工具编译与元数据文件剖析

本篇包含以下内容:

  • 与事务相关的数据结构是如何支撑事务的?
  • MongoDB事务采取的多版本并发控制机制(MVCC)

事务的数据结构

事务在内存里面也会维护相应的数据结构以支撑事务的并发、回滚、持久化等操作,事务相关的数据结构如下图所示:

图:事务相关的数据结构

上图左边是一个leaf page在内存的数据结构,放在这的目的是为了更好的看到内存里的修改操作与事务的关系,本节重点关注事务的数据结构即WT_TXN,详细描述如下:

id字段

这是事务的全局唯一标识,通过它与具体的操作关联,这样就能知道一个事务里面包含哪些操作。

snapshot_data字段

因为MongoDB使用的是快照隔离级别的事务,这个字段保存事务的快照信息,具体来说它会有snap_min和snap_max两个属性,通过这两个属性能够计算一个事务开始时能够看到的数据范围,每个事务开始时都会构造一个这样的快照。

commit_timestamp字段

表示事务提交的时间。

durable_timestamp字段

表示事务修改的数据已持久化的时间,与具体操作里面的durable_ts字段关联。

prepare_timestamp字段

表示事务开始准备的时间。

WT_TXN_OP字段

包含事务的修改操作,用于事务rollback和生成事务的Journal日志。

logrec字段

表示事务日志的缓存,用于在内存里面保存事务日志(对于MongoDB来Journal日志就是事务日志)。

MVCC并发控制机制

要实现事务间的并发操作,可以使用锁机制或MVCC控制等。

对于WiredTiger来说,使用的是MVCC控制来实现并发的,相较于其它锁机制的并发,MVCC实现的是一种乐观并发机制,因此它较轻量级。

MVCC是通过在内存里面维护一个多版本的行数据(leaf page上的WT_UPDATE结构),也就是说它会将多个写操作,针对同一行记录的修改以不同行版本号的形式保存下来,实现事务的并发。

具体如何实现事务并发与冲突检查,如下图所示:

图:MVCC并发控制机制

详细描述如下:

1) A事务首先从表中读取到要修改的行数据,读取到库存值为100,行记录的版本号为1;

2) B事务也从中读取到要修改的相同行数据,读取库存值为100,行记录版本号为1;

3) A事务修改库存值后提交,同时行记录版本号加1,即变为2,大于一开始读取到的版本号1,A事务可以提交;

4) 但B事务提交时发现此时行记录版本号已经变为2,产生冲突,B事务提交失败;

5) B事务尝试重新提交,此时再读取到的版本号为2,加1,即变为3,不会产生冲突,正常提交B事务。

下面再通过一段代码来分析事务的并发与冲突:

session1 = client.start_session()#开启一个session1
session1.start_transaction()#开启一个事务1
inventory.delete_one({'_id':4}, session=session1)
doc1 = inventory.find_one({'_id': 4},session=session1)
pprint.pprint(doc1)#会输出none,说明在事务里面已经删除


session2 = client.start_session()#再开启一个session2
session2.start_transaction()#在session2中开启一个事务
inventory.delete_one({_id:4}, session=session2)#执行会发生事务冲突


session1.abort_transaction()#终止事务1
session1.end_session()#结束session1
session2.abort_transaction()#终止事务2
session2.end_session()#结束session2


doc2 = inventory.find_one({'_id': 4})#隐式开启第三个session和事务
pprint.pprint(doc2)#在事务外可以找到,说明事务1被终止后,回滚了

其中语句:doc1 = inventory.find_one({'_id': 4},session=session1),在session1内部查询,数据已被删除,访问不到;

语句:inventory.delete_one({‘_id’:4}, session=session2),两个未提交的事务(session1和session2中的删除操作),同时修改相同的文档,则产生冲突。

专栏作者:郭远威

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-09-02,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Mongoing中文社区 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • WiredTiger存储引擎之一:基础数据结构分析
  • WiredTiger存储引擎之二:一个Page的生命周期
  • WiredTiger存储引擎之三:Checkpoint原理
  • WiredTiger存储引擎之四:WT工具编译与元数据文件剖析
相关产品与服务
云数据库 MongoDB
腾讯云数据库 MongoDB(TencentDB for MongoDB)是腾讯云基于全球广受欢迎的 MongoDB 打造的高性能 NoSQL 数据库,100%完全兼容 MongoDB 协议,支持跨文档事务,提供稳定丰富的监控管理,弹性可扩展、自动容灾,适用于文档型数据库场景,您无需自建灾备体系及控制管理系统。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档