上海架构师集结!4月25-26日,全球架构师峰会首次落地上海,吴翰清、汪源、叶绍志等大咖确认出席 了解详情
写点什么

快照隔离而非 ACID:MongoDB 数据一致性能力遭质疑

2020 年 6 月 02 日

快照隔离而非ACID:MongoDB数据一致性能力遭质疑

在一篇题为“MongoDB和Jepsen”的文章中,MongoDB 官方声称他们的数据库通过了“业界最严格的数据安全性、正确性和一致性测试”。作为回应,Jepsen 官方发表了一篇文章,指出 MongoDB 3.6.4 实际上没有通过他们的测试,而 MongoDB 4.2.6 的问题则更多,包括“回溯关联性事务”(回溯关联性事务是指事务会反转操作顺序,让读操作可以看到未来写操作的结果)。


Jepsen 在官方 Twitter 上对 Maxime Beugnet 做出了回复:


不得不承认,在看到那个网页时,我大吃一惊。在测试报告中,MongoDB 不仅丢失数据,还违背了关联关系,它怎么就成为“当今所有可用数据库中具有最强大的数据一致性、正确性和安全性保证的数据库之一呢”!


上述的报告出自 Kit Patella 的一篇题为“MongoDB 3.6.4”的文章,而 Kyle Kingsbury 的新报告对此进行了扩展:


类似地,MongoDB 的默认读选项允许中止读,即读操作可以观察到未完全提交并可能在未来被丢弃的状态。正如“读隔离级别一致性”文档所指出的:“读未提交是默认的隔离级别”。

我们发现,由于这些默认设置,MongoDB 的关联会话在默认情况下并不会保持关联一致性:用户需要同时指定写操作和读操作的选项为“majority”才能获得关联一致性。MongoDB 关掉了这个问题,说原本就是这样设计的,并更新了隔离级别文档,说即便 MongoDB 提供了“客户端会话的关联一致性”,但并不保证,除非用户小心使用读操作和写操作选项。现在,文档中有一个表格详细描述了较弱的读写关注点属性。


失败的事务隔离

近年来,MongoDB 一直在大力推广它的事务能力。但 Jepsen 发现,在默认情况下 MongoDB 的事务能力并不奏效。在一次测试中,他们通过事务向文档中追加数据。他们发现,即使在数据库/集合级别设置了“majority”写选项,但在事务级别设置了默认的写选项,那么“事务似乎会丢掉已确认的写操作”(这可以通过在事务级别显式指定写选项来解决)。


客户端看到一个元素单调递增的列表[1 2 3 4 5 6 7],此时列表重置为[],并使用[8]重新开始。这可能是 MongoDB 回滚的一个例子,是“数据丢失”的一种奇特说法。

那么一个更微妙的问题出现了:为什么我们能够读到这些值?毕竟,读选项应该只显示多数确认的(即持久化的)写操作。答案有点令人惊讶,文档中写提到了 MongoDB 的设计:

事务中的操作使用的是事务级别的读选项,也就是说,在集合和数据库级别设置的任何读选项在事务内部都会被忽略。


这意味着“没有显式声明读选项的事务会将数据库或集合级别的请求读选项降级为局部默认级别”,从而允许事务读取未提交的数据,而这些数据稍后可能会被回滚。


反过来也是有问题的。根据文档所述,“如果事务没有对提交的数据使用‘majority’写选项,“snapshot”读选项不能保证读操作使用的是通过‘majority’选项提交的数据的快照”。换句话说,在没有设置写选项的情况下,“snapshot”读选项将被忽略。同样,这个是发生在事务级别,因为事务忽略了集合和数据库级别的设置。


回溯关联性事务

即使使用快照隔离,也可能会出现很多意外的结果。它们中的大多数都太复杂了,其中有一个很突出。


在一次测试中,Jepsen 的研究人员使用客户端读取文档,然后向它追加数据。在测试开始时,文档包含序列[2,3,4]。读取数值后,文档被改为[1,2,3,4]。


这通常是有效的,但要在四个事务中从数据库中读取[1、2、3、4],Kingsbury 继续写道:


当然,这是不可能的:我们的测试严格按照顺序提交事务的操作,除非 MongoDB 有时间机器,否则它不可能返回还没有被写入的值。这说明回溯性事务实际上执行了两次,并且在第二次执行时看到了其自身先前执行的结果。这可能是因为不恰当的重试机制导致的结果。


这并不是唯一一次重试机制被人们指责。


我们发现,网络分区可能会导致 MongoDB 重复执行事务。尽管不会将相同的值追加到一个数组两次,但我们发现了数组会包含相同元素的多个副本。


为了更好地理解这些行为,研究人员试图禁用自动重试,结果发现“MongoDB 事务忽略了 retryWrites 设置,仍然会重试”。


除了为开发人员提供如何更安全地使用 MongoDB 的建议之外,Jepsen 还建议“MongoDB 修改营销描述,使用‘快照隔离’而不是‘ACID’”。


编后语:之前的文章暗示在使用事务时总是会发生数据丢失,实际上这个问题只会在使用事务默认写选项时发生。但是,使用“majority”写选项的事务也出现了其他异常。


原文链接


Jepsen Disputes MongoDB’s Data Consistency Claims


2020 年 6 月 02 日 09:141512

评论 1 条评论

发布
用户头像
这些问题在4.4里解决了吗
2021 年 02 月 05 日 16:29
回复
没有更多了
发现更多内容

在龙门吊上,看到破浪而来的智能时代

脑极体

翻译:如何编写Golang代码(How to Write Go Code)

申屠鹏会

golang 翻译

同行分析优化

誓约·追光者

Sparksql 优化

360 Atlas生产环境使用心得

心平气和

MySQL 分库分表 Proxy Atlas

话题讨论 | 特斯拉和拼多多杠上了,你有什么看法?

InfoQ写作平台官方

写作平台 话题讨论

突破内存限制的高性能排序

架构师修行之路

CentOS 7 配置Supervisor 服务遇到的坑总结

BigYoung

centos 报错 Supervisor

开发者关系(DevRel)的新手指南

开发者关系

开发者关系 开发者运营 技术运营 开源社区

Linux之crontab命令

王坤祥

Linux crontab

Linux数据流重定向

王坤祥

Linux linux操作

物流与区块链加供应链的现状与未来趋势

CECBC区块链专委会

行业资讯 区块链技术 供应链

RPC原理

石刻掌纹

二叉树的遍历(前序、中序、后序)

申屠鹏会

golang 算法 二叉树

TCP/IP学习(1):创建套接字

申屠鹏会

TCP 网络 TCP/IP

linux入门系列3--常见的linux远程登陆管理工具

黑马腾云

Linux xshell securecrt putty finallshell

Django2.x中url路由的path()与re_path()参数解释

BigYoung

django path url re_path 参数

范型的下一步

申屠鹏会

golang 翻译

linux入门系列4--vi/vim编辑器

黑马腾云

vim Linux centos7 操作系统 VI

Mac JetBrains(IDE)常用快捷键

王坤祥

JetBrains 快捷键

CIC国信公链:做坚实的底层技术支撑,让区块链为现代农业插上腾飞的翅膀

CNG农业公链

区块链 农业发展 CIC国信公链 CNG农业链 赵其刚

Django 表单处理流程详解

BigYoung

django 表单 流程

随着区块链技术的成熟,全球企业开始拥抱公共区块链

CECBC区块链专委会

区块链技术 公共区块链

散列表高级应用之把用户访问记录优化到极致

架构师修行之路

哈希表 数据结构与算法

TypeScript 设计模式之观察者模式

pingan8787

typescript 前端 设计模式

Windows AD巡检报错处理

BigYoung

windows AD 报错 巡检

吐血整理Windows电脑入侵自检大全

BigYoung

黑客 windows 日志 异常 自检

彻底解决雪花算法时间回拨问题新方案

柿子

算法 雪花算法

9个典型的开发者关系面试题

开发者关系

开发者关系 开发者运营 技术运营 开源社区

定义“开发者关系”

开发者关系

开发者关系 开发者运营 技术运营 开源社区

linux入门系列5--新手必会的linux命令

黑马腾云

Linux centos7 Shell linux命令 linux操作

跟我一起基于Karma搭建一个测试环境(上)

Jack Q

前端进阶训练营 Karma 测试框架搭建

OCR技术的未来发展与演进

OCR技术的未来发展与演进

快照隔离而非ACID:MongoDB数据一致性能力遭质疑-InfoQ