我有一个包含超过五十万个文档的大型集合,我需要不断更新。为实现这一目标,我的第一种方法是使用w=1
来确保写入结果,这会导致很多延迟。
collection.update(
{'_id': _id},
{'$set': data},
w=1
)
所以我决定在我的更新方法中使用w=0
,现在性能明显加快了。
由于我过去对mongodb的痛苦经历,我不确定w=0
时是否保证所有更新。我的问题是,是否可以保证使用w=0
进行更新?
修改:另外,我想知道它是如何工作的?它是否创建内部队列并逐个异步执行更新?我看到使用mongostat
,即使在python脚本退出后也正在处理某些更新。或者更新是即时的?
编辑2 :根据Sammaye的回答link,任何错误都可能导致无声失败。但是如果给出了大量的更新,会发生什么?有些更新失败了吗?
答案 0 :(得分:2)
不,w=0
可能会失败,只有:
http://docs.mongodb.org/manual/core/write-concern/#unacknowledged
Unacknowledged类似于忽略的错误;但是,驱动程序将尽可能尝试接收和处理网络错误。
这意味着写入可能在MongoDB本身内无声地失败。
如果您希望特别保证,这是不可靠的。在一天结束时,如果您想触摸数据库并从中获得确认,那么您必须等待,物理定律。
答案 1 :(得分:2)
w:0
是否保证更新?正如Sammaye写道:不,因为可能有一段时间数据仅应用于内存数据而尚未写入日志。因此,如果在此期间出现中断,根据配置,中断位于10(带有j:1
且日志和数据文件位于不同的块设备上)和默认值100毫秒之间,您的更新可能会丢失
请注意,非法更新(例如更改文档的_id
)会无声地失败。
w:0
一起使用?假设没有网络错误,驱动程序会在将操作发送到具有w:0
的mongod / mongos实例后立即返回。但是,让我们进一步了解一下在幕后发生的事情。
接下来,更新将由查询优化器处理并应用于内存数据集。在成功应用操作之后,写入关注w:1
的写入将立即返回。所应用的操作将每隔commitIntervalMs同步到期刊,并以写入关注j:1
除以3。如果您有{j:1}
的写入问题,则在将操作成功存储在 期刊后,驱动程序将返回。请注意,仍有边缘情况,如果现在发生非常“好”的定时中断,则将其发送到日志的数据将不会应用于副本集成员。
默认情况下,每个syncPeriodSecs,日记中的数据都会应用于实际的数据文件。
关于你在mongostat中看到的内容:它的粒度不是很高,你可能会在过去发生的操作。如上所述,对内存数据的更新不是即时的,因为更新首先必须通过查询优化器。
w:0
?一般情况下,说“不”是安全的。这就是为什么:
对于每个连接,分配了一定量的RAM。如果负载太高以至于mongo无法分配任何进一步的RAM,则会出现连接错误 - 无论写入问题如何,都会处理,除了未确认的写入。
此外,对内存数据的更新应用非常快 - 如果我们讨论负载峰值,很可能仍然比中更快。如果mongod完全超载(例如150k在带有旋转磁盘的独立mongod上更新一秒),当然可能会出现问题,尽管通常从底层操作系统的持久性角度来看也是如此。
但是,如果写入问题为w:0,j:0
,并且在更新未同步到日志时发生中断,则更新仍可能会在发生中断时无声地消失。
j:1
的写作问题。通过适当的设置,您可以将延迟减少到略超过10毫秒。w:0,j:0
进行写操作,以防您对数据持久性有任何保证。使用你自己的风险。这种写入问题仅适用于“廉价”数据,这些数据很容易重新获得,或者速度问题超出耐用性需求。大规模收集实时天气数据就是一个例子 - 系统仍然有效,即使这里和那里缺少一个或两个数据点。对于大多数应用程序,耐用性是的一个问题。结论:使用w:1,j:1
至少进行持久写入。