jjzjj

MongoDB 写入和锁定进程

coder 2023-10-27 原文

我最近读了很多关于 MongoDB 的文章,但我找不到任何明确的 Material ,就是数据如何写入日志和 oplog。

这就是我目前理解的流程,不对的地方请指正

  • 客户端连接到 mongod 并执行写入。写入存储在套接字缓冲区
  • 当 Mongo 可用时(此时不确定可用意味着什么),数据会写入日志吗?
  • 然后 mongoDB 文档说每 60 秒写入一次从日志刷新到磁盘上。通过这个我只能假设这意味着写入主要和操作日志。如果是这种情况,写入如何出现早于 60 秒同步间隔?
  • 一段时间后,辅助节点从主节点或其同步源获取数据并更新其操作日志和数据库。对于这种情况的确切时间和延迟时间似乎非常模糊。

我还想知道是否禁用了日记功能(我知道这是一个非常糟糕的主意),oplog 和数据库什么时候更新?

最后,我对这个过程中的哪些点创建了写锁感到有点困惑。是在数据库和oplog更新的时候,还是在其他时候?

感谢任何可以阐明这一点或为我指出一些阅读 Material 的人。

西蒙

最佳答案

据我了解,这是发生了什么。我简化了一点,但它应该清楚它是如何工作的。

  1. 客户端连接到 mongo。到目前为止没有完成任何写入,也没有断开任何连接,因为这实际上取决于现在发生的写入问题。假设我们使用(在撰写本文时)默认的“已确认”。
  2. 客户端发送它的写操作。这是我真的不确定的地方。在此步骤或下一个步骤之后,确认将发送给驱动程序。
  3. 写入操作通过查询优化器运行。这是发送确认的地方,因为在确认的写入问题中,您可能会返回重复键错误。这可能是在最后一步检查过的。如果我敢打赌,我会说是在这个之后。
  4. 然后将查询优化器的输出应用到内存中的数据,实际上应用到内存映射数据文件的数据、内存映射的 oplog 和日志的内存映射文件。从这个内存映射部分回答查询,或者将相应的数据映射到内存以回答查询。如果存在,也会从内存中读取操作日志。
  5. 日志通常每 100 毫秒同步到磁盘。精确值由许多因素决定,其中之一是 journalCommitInterval configuration parameter .如果您有日志记录的写入问题,现在会通知驱动程序。
  6. 每个 syncDelay秒,内存映射文件的当前状态已同步到磁盘 我认为日志被截断为尚未应用于数据的条目,但我不太确定因为基本上不会发生日志中的数据尚未应用于当前数据的情况。

如果仔细阅读,您会注意到数据早在通过查询优化器运行并应用于映射到内存的文件时就已准备好用于 oplog。当其中一个辅助节点拉取 oplog 条目时,它会立即应用于内存映射文件的数据,并以与主节点相同的方式在磁盘中同步。

一些注意事项:比较小的数据一旦写入日志,还是比较安全的。如果节点在两次同步到数据文件之间出现故障,则数据文件和操作日志都可以从数据文件和日志中的最后状态恢复。通常,您可以拥有的最大数据丢失是上次提交后记录到日志中的操作,中位数为 50 毫秒。

至于锁。如果您仔细编写,当数据同步到磁盘时,不会在数据库级别强加锁。可以创建写锁以确保在任何给定时间点只有一个线程修改给定文档。可能还有其他写锁,但一般来说,它们应该很少见。

文件系统层上的写锁只创建一次,尽管只是隐式地创建,iirc。在应用程序启动期间,在 dbpath 的根目录中创建一个锁定文件。当存在有效锁时,任何其他 mongod 实例将拒绝对这些数据文件执行任何操作。你也不应该 ;)

希望这对您有所帮助。

关于MongoDB 写入和锁定进程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25874644/

有关MongoDB 写入和锁定进程的更多相关文章

  1. ruby - 在 jRuby 中使用 'fork' 生成进程的替代方案? - 2

    在MRIRuby中我可以这样做:deftransferinternal_server=self.init_serverpid=forkdointernal_server.runend#Maketheserverprocessrunindependently.Process.detach(pid)internal_client=self.init_client#Dootherstuffwithconnectingtointernal_server...internal_client.post('somedata')ensure#KillserverProcess.kill('KILL',

  2. Ruby 写入和读取对象到文件 - 2

    好的,所以我的目标是轻松地将一些数据保存到磁盘以备后用。您如何简单地写入然后读取一个对象?所以如果我有一个简单的类classCattr_accessor:a,:bdefinitialize(a,b)@a,@b=a,bendend所以如果我从中非常快地制作一个objobj=C.new("foo","bar")#justgaveitsomerandomvalues然后我可以把它变成一个kindaidstring=obj.to_s#whichreturns""我终于可以将此字符串打印到文件或其他内容中。我的问题是,我该如何再次将这个id变回一个对象?我知道我可以自己挑选信息并制作一个接受该信

  3. ruby - 通过 ruby​​ 进程共享变量 - 2

    我正在编写一个gem,我必须在其中fork两个启动两个webrick服务器的进程。我想通过基类的类方法启动这个服务器,因为应该只有这两个服务器在运行,而不是多个。在运行时,我想调用这两个服务器上的一些方法来更改变量。我的问题是,我无法通过基类的类方法访问fork的实例变量。此外,我不能在我的基类中使用线程,因为在幕后我正在使用另一个不是线程安全的库。所以我必须将每个服务器派生到它自己的进程。我用类变量试过了,比如@@server。但是当我试图通过基类访问这个变量时,它是nil。我读到在Ruby中不可能在分支之间共享类变量,对吗?那么,还有其他解决办法吗?我考虑过使用单例,但我不确定这是

  4. ruby-on-rails - Rails - 乐观锁定总是触发 StaleObjectError 异常 - 2

    我正在学习Rails,并阅读了关于乐观锁的内容。我已将类型为integer的lock_version列添加到我的articles表中。但现在每当我第一次尝试更新记录时,我都会收到StaleObjectError异常。这是我的迁移:classAddLockVersionToArticle当我尝试通过Rails控制台更新文章时:article=Article.first=>#我这样做:article.title="newtitle"article.save我明白了:(0.3ms)begintransaction(0.3ms)UPDATE"articles"SET"title"='dwdwd

  5. ruby - Ruby 是否使用 $stdout 来写入 puts 和 return 的输出? - 2

    我想知道Ruby用来在命令行打印这些东西的输出流:irb(main):001:0>a="test"=>"test"irb(main):002:0>putsatest=>nilirb(main):003:0>a=>"test"$stdout是否用于irb(main):002:0>和irb(main):003:0>?而且,在这两次调用之间,$stdout的值是否有任何变化?另外,有人能告诉我打印/写入这些内容的Ruby源代码吗? 最佳答案 是的。而且很容易向自己测试/证明。在命令行试试这个:ruby-e'puts"foo"'>test.

  6. ruby - 无法在 Ruby 中将 ffmpeg 作为子进程运行 - 2

    我正在尝试使用以下代码通过将ffmpeg实用程序作为子进程运行并获取其输出并解析它来确定视频分辨率:IO.popen'ffmpeg-i'+path_to_filedo|ffmpegIO|#myparsegoeshereend...但是ffmpeg输出仍然连接到标准输出并且ffmepgIO.readlines是空的。ffmpeg实用程序是否需要一些特殊处理?或者还有其他方法可以获得ffmpeg输出吗?我在WinXP和FedoraLinux下测试了这段代码-结果是一样的。 最佳答案 要跟进mouviciel的评论,您需要使用类似pope

  7. Ruby 守护进程导致 ActiveRecord 记录器 IOError - 2

    我目前正在用Ruby编写一个项目,它使用ActiveRecordgem进行数据库交互,我正在尝试使用ActiveRecord::Base.logger记录所有数据库事件具有以下代码的属性ActiveRecord::Base.logger=Logger.new(File.open('logs/database.log','a'))这适用于迁移等(出于某种原因似乎需要启用日志记录,因为它在禁用时会出现NilClass错误)但是当我尝试运行包含调用ActiveRecord对象的线程守护程序的项目时脚本失败并出现以下错误/System/Library/Frameworks/Ruby.frame

  8. ruby - 在 ruby​​ 中生成一个进程,捕获 stdout,stderr,获取退出状态 - 2

    我想从ruby​​rake脚本运行一个可执行文件,比如foo.exe我希望将foo.exe的STDOUT和STDERR输出直接写入我正在运行rake任务的控制台.当进程完成时,我想将退出代码捕获到一个变量中。我如何实现这一目标?我一直在玩backticks、process.spawn、system但我无法获得我想要的所有行为,只有部分更新:我在Windows上,在标准命令提示符下,而不是cygwin 最佳答案 system获取您想要的STDOUT行为。它还返回true作为零退出代码,这可能很有用。$?填充了有关最后一次system调

  9. ruby-on-rails - 如何用不同的用户运行nginx主进程 - 2

    A/ctohttp://wiki.nginx.org/CoreModule#usermaster进程曾经以root用户运行,是否可以以不同的用户运行nginxmaster进程? 最佳答案 只需以非root身份运行init脚本(即/etc/init.d/nginxstart),就可以用不同的用户运行nginxmaster进程。如果这真的是你想要做的,你将需要确保日志和pid目录(通常是/var/log/nginx&/var/run/nginx.pid)对该用户是可写的,并且您所有的listen调用都是针对大于1024的端口(因为绑定(

  10. Ruby:写入 stdin 并从 stdout 读取? - 2

    我正在编写一个ruby​​程序,它应该执行另一个程序,通过stdin向它传递值,从它的stdout读取响应,然后打印响应。这是我目前所拥有的。#!/usr/bin/envrubyrequire'open3'stdin,stdout,stderr=Open3.popen3('./MyProgram')stdin.puts"helloworld!"output=stdout.readerrors=stderr.readstdin.closestdout.closestderr.closeputs"Output:"puts"-------"putsoutputputs"\nErrors:"p

随机推荐