MongoDB · 引擎特性 · 事务实现解析

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云数据库 MongoDB,独享型 2核8GB
推荐场景:
构建全方位客户视图
云原生多模数据库 Lindorm,多引擎 多规格 0-4节点
简介: MongoDB 4.0 引入的事务功能,支持多文档ACID特性,例如使用 mongo shell 进行事务操作> s = db.getMongo().startSession()session { "id" : UUID("3bf55e90-5e88-44aa-a59e-a30f777f1d89") }> s.

MongoDB 4.0 引入的事务功能,支持多文档ACID特性,例如使用 mongo shell 进行事务操作

> s = db.getMongo().startSession()
session { "id" : UUID("3bf55e90-5e88-44aa-a59e-a30f777f1d89") }
> s.startTransaction()
> db.coll01.insert({x: 1, y: 1})
WriteResult({ "nInserted" : 1 })
> db.coll02.insert({x: 1, y: 1})
WriteResult({ "nInserted" : 1 })
> s.commitTransaction()  (或者 s.abortTransaction()回滚事务)

支持 MongoDB 4.0 的其他语言 Driver 也封装了事务相关接口,用户需要创建一个 Session,然后在 Session 上开启事务,提交事务。例如

python 版本

with client.start_session() as s:
    s.start_transaction()
    collection_one.insert_one(doc_one, session=s)
    collection_two.insert_one(doc_two, session=s)
    s.commit_transaction()

java 版本

try (ClientSession clientSession = client.startSession()) {
   clientSession.startTransaction();
   collection.insertOne(clientSession, docOne);
   collection.insertOne(clientSession, docTwo);
   clientSession.commitTransaction();
}

Session

Session 是 MongoDB 3.6 版本引入的概念,引入这个特性主要就是为实现多文档事务做准备。Session 本质上就是一个「上下文」。

在以前的版本,MongoDB 只管理单个操作的上下文,mongod 服务进程接收到一个请求,为该请求创建一个上下文 (源码里对应 OperationContext),然后在服务整个请求的过程中一直使用这个上下文,内容包括,请求耗时统计、请求占用的锁资源、请求使用的存储快照等信息。有了 Session 之后,就可以让多个请求共享一个上下文,让多个请求产生关联,从而有能力支持多文档事务。

每个 Session 包含一个唯一的标识 lsid,在 4.0 版本里,用户的每个请求可以指定额外的扩展字段,主要包括:

  • lsid: 请求所在 Session 的 ID, 也称 logic session id
  • txnNmuber: 请求对应的事务号,事务号在一个 Session 内必须单调递增
  • stmtIds: 对应请求里每个操作(以insert为例,一个insert命令可以插入多个文档)操作ID

实际上,用户在使用事务时,是不需要理解这些细节,MongoDB Driver 会自动处理,Driver 在创建 Session 时分配 lsid,接下来这个 Session 里的所以操作,Driver 会自动为这些操作加上 lsid,如果是事务操作,会自动带上 txnNumber。

值得一提的是,Session lsid 可以通过调用 startSession 命令让 server 端分配,也可以客户端自己分配,这样可以节省一次网络开销;而事务的标识,MongoDB 并没有提供一个单独的 startTransaction的命令,txnNumber 都是直接由 Driver 来分配的,Driver 只需保证一个 Session 内,txnNumber 是递增的,server 端收到新的事务请求时,会主动的开始一个新事务。

MongoDB 在 startSession 时,可以指定一系列的选项,用于控制 Session 的访问行为,主要包括:

ACID

Atomic

针对多文档的事务操作,MongoDB 提供 “All or nothing” 的原子语义保证。

Consistency

太难解释了,还有抛弃 Consistency 特性的数据库?

Isolation

MongoDB 提供 snapshot 隔离级别,在事务开始创建一个 WiredTiger snapshot,然后在整个事务过程中使用这个快照提供事务读。

Durability

事务使用 WriteConcern {j: ture} 时,MongoDB 一定会保证事务日志提交才返回,即使发生 crash,MongoDB 也能根据事务日志来恢复;而如果没有指定 {j: true} 级别,即使事务提交成功了,在 crash recovery 之后,事务的也可能被回滚掉。

事务与复制

复制集配置下,MongoDB 整个事务在提交时,会记录一条 oplog(oplog 是一个普通的文档,所以目前版本里事务的修改加起来不能超过文档大小 16MB的限制),包含事务里所有的操作,备节点拉取oplog,并在本地重放事务操作。

事务 oplog 示例,包含事务操作的 lsid,txnNumber,以及事务内所有的操作日志(applyOps字段)

“ts” : Timestamp(1530696933, 1), “t” : NumberLong(1), “h” : NumberLong(“4217817601701821530”), “v” : 2, “op” : “c”, “ns” : “admin.$cmd”, “wall” : ISODate(“2018-07-04T09:35:33.549Z”), “lsid” : { “id” : UUID(“e675c046-d70b-44c2-ad8d-3f34f2019a7e”), “uid” : BinData(0,”47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=”) }, “txnNumber” : NumberLong(0), “stmtId” : 0, “prevOpTime” : { “ts” : Timestamp(0, 0), “t” : NumberLong(-1) }, “o” : { “applyOps” : [ { “op” : “i”, “ns” : “test.coll2”, “ui” : UUID(“a49ccd80-6cfc-4896-9740-c5bff41e7cce”), “o” : { “_id” : ObjectId(“5b3c94d4624d615ede6097ae”), “x” : 20000 } }, { “op” : “i”, “ns” : “test.coll3”, “ui” : UUID(“31d7ae62-fe78-44f5-ba06-595ae3b871fc”), “o” : { “_id” : ObjectId(“5b3c94d9624d615ede6097af”), “x” : 20000 } } ] } }

整个重放过程如下:

  1. 获取当前 Batch (后台不断拉取 oplog 放入 Batch)
  2. 设置 OplogTruncateAfterPoint 时间戳为 Batch里第一条 oplog 时间戳 (存储在 local.replset.oplogTruncateAfterPoint 集合)
  3. 写入 Batch 里所有的 oplog 到 local.oplog.rs 集合,根据 oplog 条数,如果数量较多,会并发写入加速
  4. 清理 OplogTruncateAfterPoint, 标识 oplog 完全成功写入;如果在本步骤完成前 crash,重启恢复时,发现 oplogTruncateAfterPoint 被设置,会将 oplog 截短到该时间戳,以恢复到一致的状态点。
  5. 将 oplog 划分到到多个线程并发重放,为
目录
相关文章
|
运维 监控 NoSQL
【MongoDB 复制集秘籍】Secondary 同步慢怎么办?深度解析与实战指南,让你的数据库飞速同步!
【8月更文挑战第24天】本文通过一个具体案例探讨了MongoDB复制集中Secondary成员同步缓慢的问题。现象表现为数据延迟增加,影响业务运行。经分析,可能的原因包括硬件资源不足、网络状况不佳、复制日志错误等。解决策略涵盖优化硬件(如增加内存、升级CPU)、调整网络配置以减少延迟以及优化MongoDB配置(例如调整`oplogSize`、启用压缩)。通过这些方法可有效提升同步效率,保证系统的稳定性和性能。
357 4
|
9月前
|
NoSQL 关系型数据库 Shell
Mongodb支持事务吗?
MongoDB 是一个非关系型数据库,最初不支持事务。4.0版本引入了多文档事务支持,确保跨多个文档的操作要么全部成功,要么全部失败回滚,保持数据一致性。从4.2版本起,分布式事务和多文档事务成为同义词,支持分片集群和副本集上的多文档操作。配置事务需开启副本集,并通过会话管理事务的提交与回滚。示例展示了如何在MongoDB Shell中使用事务进行多文档操作。
888 11
|
10月前
|
存储 NoSQL MongoDB
MongoDB面试专题33道解析
大家好,我是 V 哥。今天为大家整理了 MongoDB 面试题,涵盖 NoSQL 数据库基础、MongoDB 的核心概念、集群与分片、备份恢复、性能优化等内容。这些题目和解答不仅适合面试准备,也是日常工作中深入理解 MongoDB 的宝贵资料。希望对大家有所帮助!
282 7
|
11月前
|
存储 NoSQL MongoDB
MongoDB 概念解析
10月更文挑战第12天
235 0
MongoDB 概念解析
|
存储 SQL 关系型数据库
深入解析MySQL事务机制和锁机制
深入解析MySQL事务机制和锁机制
|
C# 开发者 Windows
全面指南:WPF无障碍设计从入门到精通——让每一个用户都能无障碍地享受你的应用,从自动化属性到焦点导航的最佳实践
【8月更文挑战第31天】为了确保Windows Presentation Foundation (WPF) 应用程序对所有用户都具备无障碍性,开发者需关注无障碍设计原则。这不仅是法律要求,更是社会责任,旨在让技术更人性化,惠及包括视障、听障及行动受限等用户群体。
326 0
|
Java 前端开发 Spring
技术融合新潮流!Vaadin携手Spring Boot、React、Angular,引领Web开发变革,你准备好了吗?
【8月更文挑战第31天】本文探讨了Vaadin与Spring Boot、React及Angular等主流技术栈的最佳融合实践。Vaadin作为现代Java Web框架,与其他技术栈结合能更好地满足复杂应用需求。文中通过示例代码展示了如何在Spring Boot项目中集成Vaadin,以及如何在Vaadin项目中使用React和Angular组件,充分发挥各技术栈的优势,提升开发效率和用户体验。开发者可根据具体需求选择合适的技术组合。
241 0
|
2月前
|
NoSQL MongoDB 数据库
数据库数据恢复—MongoDB数据库数据恢复案例
MongoDB数据库数据恢复环境: 一台操作系统为Windows Server的虚拟机上部署MongoDB数据库。 MongoDB数据库故障: 工作人员在MongoDB服务仍然开启的情况下将MongoDB数据库文件拷贝到其他分区,数据复制完成后将MongoDB数据库原先所在的分区进行了格式化操作。 结果发现拷贝过去的数据无法使用。管理员又将数据拷贝回原始分区,MongoDB服务仍然无法使用,报错“Windows无法启动MongoDB服务(位于 本地计算机 上)错误1067:进程意外终止。”
|
2月前
|
缓存 NoSQL Linux
在CentOS 7系统中彻底移除MongoDB数据库的步骤
以上步骤完成后,MongoDB应该会从您的CentOS 7系统中被彻底移除。在执行上述操作前,请确保已经备份好所有重要数据以防丢失。这些步骤操作需要一些基本的Linux系统管理知识,若您对某一步骤不是非常清楚,请先进行必要的学习或咨询专业人士。在执行系统级操作时,推荐在实施前创建系统快照或备份,以便在出现问题时能够恢复到原先的状态。
273 79
|
2月前
|
存储 NoSQL MongoDB
MongoDB数据库详解-针对大型分布式项目采用的原因以及基础原理和发展-卓伊凡|贝贝|莉莉
MongoDB数据库详解-针对大型分布式项目采用的原因以及基础原理和发展-卓伊凡|贝贝|莉莉
166 8
MongoDB数据库详解-针对大型分布式项目采用的原因以及基础原理和发展-卓伊凡|贝贝|莉莉

相关产品

  • 云数据库 MongoDB 版
  • 推荐镜像

    更多