【问题标题】:Are there extra considerations when writing data to Mongo's "local" DB?将数据写入 Mongo 的“本地”数据库时是否有额外的注意事项?
【发布时间】:2014-01-25 00:23:03
【问题描述】:

编辑: 这里有几个观点

写入“本地”是一种合法的技术 - 来自“MongoDB: The Definitive Guide, 2nd. ED”和http://www.kchodorow.com/blog/2010/10/27/bending-the-oplog-to-your-will/

这个数据库永远不会被复制,可以用来存储任何 应该是单个服务器本地的集合

写信给“本地”从来都不是一个好主意 - 来自https://jira.mongodb.org/browse/SERVER-11670https://groups.google.com/forum/#!topic/mongodb-user/E_aPgNR1zss

不能向本地数据库写入任何内容 - 这是为了 MongoDB的使用和使用它的用户集合(避免复制 他们)不保证不会引起问题

这可能是一个好主意,也可能不是一个好主意 - http://docs.mongodb.org/manual/reference/local-database/ 的文档是不可知的


原帖:

在我的 Mongo 2.4.9 安装(Windows 和 Linux 版本)上将大约 100MB 的数据写入“本地”数据库时遇到错误。

这个错误 (https://jira.mongodb.org/browse/SERVER-11670) 看起来与我的问题相似,但我无法相信随机无法写入数据库是一个小问题,并且会推迟到 2.7。所以一定是我。

无论如何,Windows 错误如下所示:

Fri Jan 24 15:59:11.551 [conn40] mongod.exe    ...\src\mongo\util\stacktrace.cpp(167)                           mongo::printStackTrace+0x3e
Fri Jan 24 15:59:11.551 [conn40] mongod.exe    ...\src\mongo\db\dur.cpp(277)                                    mongo::dur::DurableImpl::_aCommitIsNeeded+0xe8
Fri Jan 24 15:59:11.551 [conn40] mongod.exe    ...\src\mongo\db\instance.cpp(812)                               mongo::insertMulti+0x212
Fri Jan 24 15:59:11.551 [conn40] mongod.exe    ...\src\mongo\db\instance.cpp(875)                               mongo::receivedInsert+0xaff
Fri Jan 24 15:59:11.552 [conn40] mongod.exe    ...\src\mongo\db\instance.cpp(441)                               mongo::assembleResponse+0x57a
Fri Jan 24 15:59:11.552 [conn40] mongod.exe    ...\src\mongo\db\db.cpp(194)                                     mongo::MyMessageHandler::process+0xfa
Fri Jan 24 15:59:11.552 [conn40] mongod.exe    ...\src\mongo\util\net\message_server_port.cpp(207)              mongo::PortMessageServer::handleIncomingMsg+0x578
Fri Jan 24 15:59:11.552 [conn40] mongod.exe    ...\src\third_party\boost\libs\thread\src\win32\thread.cpp(180)  boost::`anonymous namespace'::thread_start_function+0x21
Fri Jan 24 15:59:11.552 [conn40] mongod.exe    f:\dd\vctools\crt_bld\self_64_amd64\crt\src\threadex.c(314)      _callthreadstartex+0x17
Fri Jan 24 15:59:11.552 [conn40] mongod.exe    f:\dd\vctools\crt_bld\self_64_amd64\crt\src\threadex.c(292)      _threadstartex+0x7f
Fri Jan 24 15:59:11.553 [conn40] kernel32.dll                                                                   BaseThreadInitThunk+0xd
Fri Jan 24 15:59:11.553 [conn40] ERROR: can't commitNow from commitIfNeeded, as we are in local db lock

Linux 错误如下所示:

Sat Jan 25 00:20:04.558 [conn19] ERROR: can't commitNow from commitIfNeeded, as we are in local db lock
0xde46e1 0x921a65 0x921b4c 0x9f8b15 0x9f9412 0x9ffd68 0x6e8518 0xdd0cae 0x7f0cd72d8ddb 0x7f0cd667ca1d
 /usr/bin/mongod(_ZN5mongo15printStackTraceERSo+0x21) [0xde46e1]
 /usr/bin/mongod(_ZN5mongo3dur11DurableImpl16_aCommitIsNeededEv+0x155) [0x921a65]
 /usr/bin/mongod(_ZN5mongo3dur11DurableImpl14commitIfNeededEb+0x4c) [0x921b4c]
 /usr/bin/mongod(_ZN5mongo11insertMultiEbPKcRSt6vectorINS_7BSONObjESaIS3_EERNS_5CurOpE+0x45) [0x9f8b15]
 /usr/bin/mongod(_ZN5mongo14receivedInsertERNS_7MessageERNS_5CurOpE+0x862) [0x9f9412]
 /usr/bin/mongod(_ZN5mongo16assembleResponseERNS_7MessageERNS_10DbResponseERKNS_11HostAndPortE+0xab8) [0x9ffd68]
 /usr/bin/mongod(_ZN5mongo16MyMessageHandler7processERNS_7MessageEPNS_21AbstractMessagingPortEPNS_9LastErrorE+0x98) [0x6e8518]
 /usr/bin/mongod(_ZN5mongo17PortMessageServer17handleIncomingMsgEPv+0x42e) [0xdd0cae]
 /lib64/libpthread.so.0(+0x7ddb) [0x7f0cd72d8ddb]
 /lib64/libc.so.6(clone+0x6d) [0x7f0cd667ca1d]

错误是间歇性的,但通常会在 30-90 秒内以块的形式出现,在此期间我无法写入任何数据。有几次我不得不终止写入数据的进程。

说到数据,我正在编写大约 750,000 个相当简单的文档(少量字符串和一个小的嵌入式文档)。没有用户指定的索引,只有 _id 上的默认索引。

我可以期望写入“本地”数据库而不会出错吗?我了解到,对于您不想复制的数据,这是一种合法的技术。

是否有任何解决方法?特殊配置设置?我使用 Windows 安装的默认配置和 Linux 安装的轻微日志修改

【问题讨论】:

  • local 数据库仅用于 MongoDB 复制和其他内部跟踪。一般来说,写入local 数据库不是一个好主意,尤其是如果这是副本集的主数据库。您从哪里得知这是一种合法的技术?

标签: mongodb local-database


【解决方案1】:

您是否在副本集中运行?如果是这样,您看到写入被阻止的原因是所有其他线程都需要写入 oplog,这将需要获取本地 DB 上的写入锁。

阅读代码,如果未提交的数据量超过某个阈值,MongoDB 会尝试在插入线程上提交数据,但如果您使用的是本地数据库或管理数据库,则不会这样做。因此,当您反复尝试写入本地 DB 并且 MongoDB 希望插入线程提交数据时,执行这些本地 DB 写入的线程可能会崩溃。

假设您有其他线程进行写入,我怀疑,一个可能的解决方法是在您收到此错误时休眠一小段时间,以便让另一个线程有机会在不持有本地数据库的情况下提交日志。但这是阅读代码的推测。

【讨论】:

  • 我的计划是在副本集上运行,但我现在仍在单个实例上测试整体工作流程。客户端代码实际上并没有得到任何错误 - 它只是挂在我认为的套接字读取上 - 所以我不能做任何错误检测和睡眠或其他任何事情。不过是个好主意。
【解决方案2】:

local 数据库仅用于 MongoDB 复制和其他内部跟踪。

根据 Asya 对SERVER-11670 的评论:

无论这张票如何,都不能向本地数据库写入任何内容 - 它是供 MongoDB 使用的,并且将其用于用户集合(以避免复制它们)不能保证不会引起问题(除了这个问题你已经遇到)。”。

在本期中,她正在针对 oplog 测试聚合的新 $out 功能,这就是为什么受影响的版本是 2.5.3(开发/不稳定)并且 fixVersion 不确定的原因。

如果您要写入不会被复制的数据,最好的方法是设置一个单独的独立 mongod 实例。没有(在 MongoDB 2.4 中)支持将您自己的非复制数据存储在副本集部署中的方式。

【讨论】:

  • 在我将这个问题发布给 SO 之后,我看到了对我的评论的回复 - 你不能将用户数据写入本地的想法对我来说是全新的,并且不受我所拥有的文档的支持读。我错过了其他一些文档吗?
  • @EdNorris:我认为有一个相当主观的区别。从技术上讲,您可以写入local 数据库(没有什么可以阻止您这样做)。实际上,这不是经过测试或支持的配置,因此这样做可能会导致意外问题(例如您在此处报告的内容)。以我的经验,这绝对是问题多于帮助,我不建议在生产环境中写入local 数据库。
  • @EdNorris:同样值得注意的是,我和 Asya 都在 MongoDB, Inc 工作,所以我们的观点是基于客户的总体体验。如果写入local 数据库适用于您的用例,那很好.. 但我认为目前这不是一个好的或可推荐的想法(即解决您的问题“是否应该可以正常工作”) .
  • 一位 MongoDB 的前员工写了一些不同意这一点的书籍和博客文章,虽然我相信你写到本地数据库是个坏主意,但我有点担心这种差异.我将在下周的“办公时间”聚会期间前往 MongoDB 办公室,看看我能找到什么。
  • @EdNorris:我知道 Kristina 编写了权威指南,但也许从那时起,local 不那么值得推荐了。您计划去哪个办公时间(旧金山、纽约、...)?
猜你喜欢
  • 1970-01-01
  • 2014-10-10
  • 1970-01-01
  • 2012-06-12
  • 1970-01-01
  • 2014-12-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多