我不是数据库专家,也没有正式的计算机科学背景,所以请容忍我.我想知道,如果你使用一个旧的MongoDB version prior to v4,可能会发生real world种消极的事情,而这些都不符合ACID.这适用于任何不符合ACID的数据库.

我知道MongoDB可以执行Atomic Operations次,但它们"不支持传统的锁定和复杂事务",主要是出于性能原因.我也理解数据库事务的重要性,例如,当您的数据库用于银行时,您要更新多个需要同步的记录,如果停电,您希望事务恢复到初始状态,以便信用等于购买,等等.

但当我开始谈论MongoDB时,我们中那些不知道数据库实际如何实现的技术细节的人开始抛出如下语句:

MongoDB比MySQL和Postgres快得多,但它"无法正确保存"的可能性很小,如百万分之一.

"无法正确保存"部分指的是这样一种理解:如果在您向MongoDB写入内容的瞬间发生断电,则有可能出现特定的记录(例如,您正在跟踪每个文档中有10个属性的页面浏览量),其中一个文档只保存了5个属性……这意味着随着时间的推移,您的页面浏览计数器将"稍微"关闭.你永远不会知道他们的正确率是多少,你知道他们的正确率是99.999%,但不是mongodb atomic operation%.这是因为,除非你特别将其设为mongodb atomic operation,否则操作不能保证是原子的.

所以我的问题是,MongoDB何时以及为什么不能"正确保存"的正确解释是什么?它不满足ACID的哪些部分,在什么情况下,以及如何知道0.001%的数据何时关闭?这难道不能以某种方式解决吗?如果不是,这似乎意味着不应该在MongoDB中存储像users表这样的东西,因为记录可能无法保存.但话说回来,users万分之一的用户可能只需要"再次try 注册",不是吗?

我只是想找一份 list ,列出在MongoDB这样的ACID不兼容数据库中,负面事件发生的时间/原因,以及理想情况下是否有一个标准的解决方法(比如运行后台作业(job)来清理数据,或者仅使用SQL等).

推荐答案

MongoDB的一个缺点是多集合(表)事务.MongoDB中的原子修饰符只能对单个文档起作用.

如果你需要从库存中删除一个项目,同时将其添加到某人的订单中,你不能.除非这两件事——库存和订单——存在于同一个文档中(它们可能不存在).

我在正在开发的一个应用程序中遇到了同样的问题,有两种可能的解决方案可供 Select :

1) 尽可能地组织文档,尽可能地使用原子修饰符,对于剩余的部分,使用后台进程清理可能不同步的记录.例如,我从库存中删除项目,并使用原子修饰符将它们添加到同一文档的reservedInventory数组中.

这让我始终知道库存中没有商品(因为它们是由客户预订的).当顾客退房时,我会把物品从储备库中取出.这不是一个标准的交易,因为客户可以放弃购物车,所以我需要一些后台流程来查找被放弃的购物车,并将保留的库存移回可用的库存池.

这显然不太理想,但这是mongodb无法完全满足需求的大型应用程序的唯一部分.此外,到目前为止,它工作得完美无缺.这在很多情况下可能不可能实现,但由于我使用的文档 struct ,它非常适合.

2) 将事务数据库与MongoDB结合使用.通常使用MySQL为绝对需要的事务提供事务,同时让MongoDB(或任何其他NoSQL)做它最擅长的事情.

如果#1的解决方案从长远来看不起作用,我将进一步研究MongoDB与MySQL的结合,但目前#1很适合我的需要.

Sql相关问答推荐

我希望以正确的升序获取SQL结果.怎样才能得到它们?

如何查询jsonb列是一个对象数组?

用于过滤嵌套对象或数组中的JSON数据的WHERE条件

动态组/转置

SQL数据库规范化与数据插入

按用户和时间列出的SQL Group考勤列表

最小非重复集的SQL查询

组合2个分区表的postgres视图的执行计划正在访问所有分区

Haystack针相交-在元素最多的Haystack中查找集合

如何在 golang squirrel lib 中添加 postgreSQL 的distinct on

将具有嵌套 XML 的列转换为 SQL 中的表格格式?

特殊条件计算小计

验证某个日期前后的连续代码

SQL:无重复项的两个聚合函数

将表格和字符串连接以 for each 记录生成订单项目

将有效数字作为 varchar 返回的 SQL 函数

连续期间的缺口

BigQuery Pivot 遗漏行

PostgreSQL 中的递归树查询

使用同一表中的数据或任何其他虚拟数据在 SQL 表中插入数据的最快方法