MongoDB不符合ACID标准是什么意思?
我不是一个数据库专家,没有正式的计算机科学背景,所以忍受着我。 我想知道如果使用不符合ACID的 MongoDB,可能会发生的真实世界的负面情况。 这适用于任何不符合ACID的数据库。
据我所知,MongoDB可以执行primefaces操作 ,但是他们并不是“支持传统的locking和复杂事务”,主要是出于性能原因。 我也明白数据库事务的重要性,以及你的数据库是在银行的例子,而且你正在更新几个需要同步的logging,你希望事务恢复到初始状态,如果有停电,所以信贷等于购买等。
但是当我谈到MongoDB的时候,那些不知道数据库实际上是如何实现的技术细节的人开始抛出像下面这样的陈述:
MongoDB的速度比MySQL和Postgres快,但是有一个很小的机会,比如百万分之一,它“无法正确保存”。
这个“不能正确保存”的部分是指这样的理解:如果在写入MongoDB的瞬间有停电的可能,有一个特定logging的机会(比如说,你跟踪具有10个属性的文档中的浏览量每一个),其中一个文件只保存了5个属性…这意味着随着时间的推移,你的浏览量计数器将“略微”closures。 你永远不会知道多less,你知道他们将是99.999%正确,但不是100%。 这是因为,除非你专门做了这个mongodbprimefaces操作 ,否则操作不能保证是primefaces操作。
所以我的问题是,什么时候以及为什么MongoDB不能“正确保存”的正确解释? ACID的哪些部分是不能满足的,在什么情况下,您怎么知道您的数据的0.001%是什么时候closures的? 这不能以某种方式解决吗? 如果没有,这似乎意味着你不应该在MongoDB中存储像你的users
表这样的东西,因为logging可能不会保存。 但是再一次,那1 / 1,000,000用户可能只需要“尝试再次注册”,不是吗?
我只是在寻找一个什么时候/为什么负面的事情发生在一个像MongoDB这样的ACID不兼容数据库的列表,理想的情况是如果有一个标准的解决方法(如运行后台作业来清理数据,或者只使用SQL等) 。
MongoDB失去的一件事就是多次收集(表)事务。 MongoDB中的primefaces修饰符只能针对单个文档。
如果您需要从库存中删除某件商品,并同时将其添加到某人的订单中,则无法进行此操作。 除非这两个东西 – 库存和订单 – 存在于同一个文件中(他们可能不这样做)。
我在一个正在处理的应用程序中遇到了这个问题,并且存在两个可能的解决scheme:
1)尽你最大可能地构build你的文档,并尽可能地使用primefaces修饰符,并留下他的位置,使用后台进程来清理可能不同步的logging。 例如,我从库存中删除项目,并使用primefaces修饰符将它们添加到同一文档的reservedInventory数组中。
这让我总是知道物品在库存中不可用(因为它们是由客户保留的)。 当客户检查结束时,我从reservedInventory中删除这些项目。 这不是一个标准的交易,因为客户可能会放弃购物车,所以我需要一些后台stream程来查找废弃的购物车,并将预留的库存移回到可用的库存池中。
这显然不太理想,但是它是MongoDB完全不适合需求的大型应用程序的唯一部分。 另外,它迄今为止工作完美无瑕。 这在许多情况下可能是不可能的,但是由于我使用的文档结构,它很适合。
2)将事务数据库与MongoDB结合使用。 通常使用MySQL为绝对需要的事物提供事务,同时让MongoDB(或任何其他NoSQL)做最好的事情。
如果我从#1的解决scheme长期不起作用,我将进一步调查MongoDB与MySQL的结合,但现在#1适合我的需要。
实际上MongoDB不符合ACID标准是不正确的。 相反,MongoDB是文档级的 ACID编译器。
任何对单个文档的更新是
- primefaces:它要么完全完成,要么不完成
- 一致:没有读者会看到“部分应用”的更新
- 隔离:再次,没有读者会看到一个“脏”的阅读
- 耐用:(与适当的写作关注)
MongoDB没有什么是事务 – 也就是说,多文档更新可以被回滚并且符合ACID标准。
请注意,通过使用两阶段提交 ,您可以在符合ACID的更新上将事务构build到单个文档。
“星巴克不使用两阶段提交”中有一个很好的解释。
这不是关于NoSQL数据库,但它确实说明了有时你可以承受失去一个事务或暂时让你的数据库处于不一致的状态。
我不认为这是需要“固定”的东西。 解决方法是使用符合ACID的关系数据库。 当您的行为符合您的应用程序要求时,您可以selectNoSQL替代scheme
我想其他人已经给出了很好的答案。 不过,我想补充说,有ACID NOSQL数据库(如http://ravendb.net/ )。 所以这不仅是决定NOSQL – 没有ACID与ACID的关系….
“不会正确保存”可能意味着:
-
默认情况下,MongoDB不会立即将更改保存到驱动器。 因此,您可能会告诉用户“更新成功”,发生停电并且更新丢失。 MongoDB提供了控制更新“持久性”级别的选项。 它可以等待其他副本接收此更新(在内存中),等待写入发生在本地日志文件等。
-
对同一个集合中的多个集合甚至多个文档没有简单的“primefaces”更新。 在大多数情况下,这不是问题,因为它可以通过两阶段提交来绕过,或者重构您的模式,以便对单个文档进行更新。 看到这个问题: 文档数据库:冗余数据,引用等(特别是MongoDB)
primefaces修改对单个集合的唯一原因是因为mongodb开发人员最近交换了一个带有集合宽写锁的数据库锁。 决定这里增加的并发是值得的权衡。 在它的核心,mongodb是一个内存映射文件:他们已经把缓冲池pipe理委托给了机器的vm子系统。 因为它总是在内存中,所以它们能够脱离非常粗糙的锁:你将在内存中执行操作,这将是非常快的。 这与传统的数据库系统有很大的不同,传统的数据库系统有时被迫在执行页锁或行锁时执行I / O操作。
请阅读ACID属性以获得更好的理解。
同样在MongoDB文档中,您可以find问题和答案 。
MongoDB不符合ACID标准。 请阅读下面的ACID合规性讨论。
- MongoDB只是在文档级别上的
A
解决scheme。 它不符合我们从关系数据库系统得知的primefaces定义,特别是上面的链接。 从这个意义上讲,MongoDB不符合ACI的A标准。 - MongoDB默认是
C
onsitent。 但是,您可以从副本集中的辅助服务器中读取数据。 在这种情况下,你只能有最终的一致性 。 如果您不介意读取稍微过时的数据,这很有用。 - MongoDB并不保证
I
定义(同样根据上面的定义):
- 对于具有多个并发读写器的系统,在写操作返回之前,MongoDB将允许客户读取写操作的结果。
- 如果mongod在日志提交之前终止,即使写入成功返回,查询也可能读取mongod重新启动后不存在的数据。
但是 ,MongoDB会单独修改每个文档(用于插入和更新); 仅在文档级别,而不是在多文档事务。
- 关于可维护性 – 您可以使用
write concern
选项configuration此行为,但不确定。 也许有人知道更好。
我相信有一些研究正在将NoSQL推向ACID约束或类似的方向。 这是一个挑战,因为NoSQL数据库通常很快(er),而ACID约束会显着降低性能。
你可以在客户端实现primefaces多键更新(可序列化的事务),如果你的存储支持每个键的线性化并且比较和设置(MongoDB是这样的话)。 在Google的Percolator和CockroachDB中使用了这种方法,但是没有任何东西阻止您将其用于MongoDB。
我已经创build了这种交易的分步可视化 。 我希望这会帮助你理解他们。
如果读取提交的隔离级别没问题,那么看看Peter Bailis的RAMP事务是很有意义的。 他们也可以在客户端上为MongoDB实现。